Symfony comparing two entities and getting names of different fields - symfony

Is there an easy way of comparing two entities and getting the names of the fields which do not match without using an if statement for each of the them?

$foo = new Foo();
$bar = new Bar();
$array_diff = array_keys(
array_diff_key(
get_object_vars($foo),
get_object_vars($bar)
));
$array_diff will be an array that contains every property that is into an entity but not into the other - or vice-versa
I'm from my smartphone so I didn't tested it

Related

Symfony 2 custom DQL request inside an array field

I'm trying to make a custom request in my repository with a WHERE clause inside an array field. I tried something like that, not working, but can better show my problem :
$qb ->andWhere( "p.addresses[:index] = :address" )
->setParameter( "index" , $p_idLang )
->setParameter( "address" , $p_address );
Extracted from the documentation about array type:
Maps and converts array data based on PHP serialization. If you need
to store an exact representation of your array data, you should
consider using this type as it uses serialization to represent an
exact copy of your array as string in the database. Values retrieved
from the database are always converted to PHP’s array type using
deserialization or null if no data is present.
Your query doesn't make sense. You have a few options though:
Retrieve p.adresses and check using php if p.adresses[$index] = $address
Try something much less reliable but that could work:
$val_length = strlen($p_address);
$qb ->andWhere( "p.addresses LIKE :indexAddress" )
->setParameter( "indexAddress" , "%i:$p_idLang;s:$val_length:$p_address%" );
Create a new entity and a relation oneToMany between this entity and the new one.
I'd definetely try option 3. Option 1 isn't an option if the array is big or will become big in the future. I wouldn't go for option 2, but as an experiment could be worth trying.

Symfony 2 Variable Entity Naming

I feel like this shouldn't be to hard, but try as I might, I keep getting errors.
What I'm wanting to do, is to have a single "add" function that will handle the basic functionality of adding records to any / all tables. Basically, the post data will contain the table name, as well as the fields / values to be inserted. The controller itself, confirms the user has access to do these things, and then verifies the fields are valid, before creating a new instance of the entity, that's where things go haywire:
$entityName = 'Products';
$row = new $entityName(); //doesn't work
$row new Products(); //works
I haven't found a way or any examples of creating a new entity using the Entity Manager, or else that might work, because i've created functions using EM to do queries, updates, and deletes, but I just can't get this to work with the add functions.
1. Your problem is almost certainly namespacing (see below). Try this instead:
$entityName = 'My\Bundle\Entity\Products';
$row = new $entityName();
Should work. ;)
2. If you want to create new instances using an EntityManager, try this:
$entityName = 'My\Bundle\Entity\Products';
$row = $em->getClassMetadata($entityName)->newInstance();
...assuming $em is your EntityManager. :-)
3. To "prove" that your problem is namespacing, try this in a plain .php file that you run from the command line:
namespace Foo;
class Test {}
$class1 = 'Foo\Test';
$class2 = 'Test';
$x = new Test(); // Will work
$y = new $class1(); // Will work
$z = new $class2(); // Will trigger "Class 'Test' not found" fatal error
Two things:
Try with "Products" instead of 'Products'
I suppose that your entity Products has a namespace, it is required (even if you declared an use statement). So try with "My\Bundle\Entity\Products".

Create new object from existent object in DB using Symfony2 and Doctrine2

I need to create a new set of DB records by using same data that already exists. See image below:
Using this as example I need to create the same set of records but just changing the column company, less take UPC = I5TYF1UPORMYUY4JT21Z, using this info I should be able to generate two rows by just changing the company to 52 (any number). What I think is to get those records using this:
$entityStockDetailHasProductDetail = $this->getDoctrine()->getManager()->getRepository('ProductBundle:StockDetailHasProductDetail')->findBy(array(
"product" => $request->request->get('product')['id'],
"upc" => $request->request->get('product')['upc'],
));
Which returns the right records but I don't know how to continue from that point. My entity has all this methods:
$entityStockDetailHasProductDetail->setProductDetail();
$entityStockDetailHasProductDetail->setUpc();
$entityStockDetailHasProductDetail->setProduct();
$entityStockDetailHasProductDetail->setCompany();
$entityStockDetailHasProductDetail->setCondition();
$entityStockDetailHasProductDetail->setContent();
Any ideas?
Just loop over the collection, clone your entities, set the new company and persist.
$em = $this->getDoctrine()->getEntityManager('default');
$collection = $em->getRepository('YourBundle:Entity')->findBy(array('...'));
foreach ($collection as $entity) {
$newEntity = clone $entity;
$newEntity
->setId(null)
->setCompany($company)
;
$em->persist($newEntity);
}
$em->flush();

Magento: how to merge two product collections into one?

if i have two product collections is there a way to merge them into one?
for example (my final intent isn't to actually just get a collection of 2 cats, this is just to illustrate the issue):
$collection1 = Mage::getModel('catalog/category')->load(148)->getProductCollection();
$collection2 = Mage::getModel('catalog/category')->load(149)->getProductCollection();
$merged_collection = merge_collections($collection1,$collection2);
any help would be appreciated!
Assuming the items you wish to group together are of the same type and exist in the database then you can do this:
$collection1 = Mage::getModel('catalog/category')->load(148)->getProductCollection();
$collection2 = Mage::getModel('catalog/category')->load(149)->getProductCollection();
$merged_ids = array_merge($collection1->getAllIds(), $collection2->getAllIds());
// can sometimes use "getLoadedIds()" as well
$merged_collection = Mage::getResourceModel('catalog/product_collection')
->addFieldToFilter('entity_id', array('in' => $merged_ids))
->addAttributeToSelect('*');
Here I know to filter by entity_id because that is products' key field, like it is for most entity types, some flat tables have a different primary key. Often you can generalise that with one of the collection's getIdFieldName() method. Products are a bad example in this case because it's ID field name isn't filled out correctly.
Almost every (or every?) collection in Magento inherits from a Varien Data Collection. A collection is a special object that holds objects of another type. There's no method for merging collections, but you can add additional items of the appropriate type to the collection.
Code like this should get you where you want to go, although there's probably more efficient ways to loop and do the actual merging.
$collection1 = Mage::getModel('catalog/category')->load(148)->getProductCollection();
$collection2 = Mage::getModel('catalog/category')->load(149)->getProductCollection();
//load an empty collection (filter-less collections will auto-lazy-load everything)
$merged = Mage::getModel('catalog/product')->getCollection()->addFieldToFilter('entity_id',-1);
//add items from the first collection
foreach($collection1 as $item)
{
$merged->addItem($item);
}
//add items from the second collection
foreach($collection2 as $item)
{
//magento won't let you add two of the same thing to a collection
//so make sure the item doesn't already exist
if(!$merged->getItemById($item->getId()))
{
$merged->addItem($item);
}
}
//lets make sure we got something
foreach($merged as $product)
{
var_dump($product->getName());
}
I don't think there is such a method, but you can probably do something like that :
foreach ($collection1 as $item){
$collection2->addElem($item);
}
you can filter your collection directly without using 2.
$products = Mage::getModel('catalog/product');
$_collection = $products->getCollection();
->addCategoryFilter(2)
->load();
or try using 'addItem' to add your results to a collection. See also in Magento wiki
for the collection of products of several categories, you can use the following code
$collection = Mage::getModel('catalog/product')->getCollection()
->addAttributeToSelect('name')
->addAttributeToSelect('sku');
$collection->getSelect()
->join(
'catalog_category_product',
'product_id=entity_id',
array('category_id')
)
->where('catalog_category_product.category_id IN (?)', $categories);

How to use multiple filters to widen the search in Apachesolr queries

Making a search with Apachesolr, i want to add a couple of filters in hook_apachesolr_prepare_query(&$query). This works fine, except I want the filters to widen the search ('OR'), rather than narrow it ('AND').
For example, if I have 4 nodes of type:A and 3 of type:B that match a search, to filter by type:A and type:B should return 7 nodes (of type:A AND nodes of type:B), rather than 0 those of type:A which are also of type:B.
I saw a suggestion to do this using the model of nodeaccess
foreach ($filters as $filter) {
$subquery = apachesolr_drupal_query();
if (!empty($subquery)) {
$subquery->add_filter('type', $filter);
$query->add_subquery($subquery);
}
}
but this doesn't seem to work. (It doesn't return any results).
I then tried (as I have a limited number of node types) excluding the types that I don't want:
$excludes = array('A', 'B', 'C');
$excludes = array_diff($excludes, $filters);
$exclude = implode('&', $excludes);
$query->add_filter('type', $exclude, TRUE);
This method of stitching them together doesn't work (the '&' gets escaped) but neither does adding them as subqueries, similar to the manner above.
Any suggestions on how to do this?
With Drupal7 and the last apacheSolr API, you can do OR filters by doing this :
function my_module_apachesolr_query_alter($query) {
// first, create a subQuery filter to store others
// and specify there is a "OR" condition
$filter = new SolrFilterSubQuery('OR');
// next, add all filters on bundle you want, each as
// a new subQuery filter, always with "OR" condition
// and add it to the primary filter
$a = new SolrFilterSubQuery('OR');
$a->addFilter('bundle', 'A');
$filter->addFilterSubQuery( $a );
$b = new SolrFilterSubQuery('OR');
$b->addFilter('bundle', 'B');
$filter->addFilterSubQuery( $b );
$c = new SolrFilterSubQuery('OR');
$c->addFilter('bundle', 'C');
$filter->addFilterSubQuery( $c );
// finally, add the primary subQuery filter as
// subquery of the current query
$query->addFilterSubQuery( $filter );
}
And your query search about type A OR type B OR type C (all results in each types). You can combine OR / AND by changing the parameter of the SolrFilterSubQuery instanciation.
Special thanks to this page and it's author : http://fr.ench.info/blog/2012/04/03/Add-Filters-ApacheSOLR.html
I havenť played with SOLR much but I am quiete familiar with Drupal and Zend Lucene (or Drupal Lucene API).
I would suggest that you try to filter your results based on content type (because each node has its content type stored in the object).
The second idea is to change basic operator. I am not sure how it is done in SOLR but i Zend Lucene
Zend_Search_Lucene_Search_QueryParser::setDefaultOperator($operator) and Zend_Search_Lucene_Search_QueryParser::getDefaultOperator() methods, respectively.
Docs can be found in Zend Lucene Docs. Or for SOLR Solr Docs.
I hope a got your problem right.
Hope it helps :-)

Resources