1

I created a file "/app/code/local/Mage/CatalogSearch/Model/Advanced.php" and copied the core file over I'm trying to modify getProductCollection() to get only products with a certain attribute set to 'yes' in the admin.

Here is my code:

$this->_productCollection = Mage::getResourceModel('catalogsearch/advanced_collection')
            ->addAttributeToSelect(Mage::getSingleton('catalog/config')->getProductAttributes())
            ->addAttributeToSelect('mc_pin_system_avail')
            ->addMinimalPrice()
            ->addStoreFilter();
            Mage::getSingleton('catalog/product_status')->addVisibleFilterToCollection($this->_productCollection);
            Mage::getSingleton('catalog/product_visibility')->addVisibleInSearchFilterToCollection($this->_productCollection);
$this->_productCollection->addAttributeToFilter(
                array(
                    array('attribute' => 'mc_pin_system','eq'=> 1),
                    array('attribute' => 'mc_pin_system_avail','eq'=> 1)
                ));

It only returns the values with mc_pin_system_avail set to yes. Can someone tell me what I'm doing wrong??

3
  • Did you want mc_pin_system AND mc_pin_system_avail as the result or mc_pin_system OR mc_pin_system_avail? Currently, the addAttributeToFilter is an OR statement. Jun 16, 2014 at 22:27
  • Yes mc_pin_system OR mc_pin_system_avail because items with mc_pin_system will likely have mc_pin_system_avail set to 'no' in the admin area.
    – Scott Eddy
    Jun 17, 2014 at 12:24
  • interestingly enough if I change my code to this->_productCollection->addAttributeToFilter( array( array('attribute' => 'mc_pin_system','eq'=> 'something'), array('attribute' => 'mc_pin_system_avail','eq'=> 'something') )); I still get the mc_pin_system_avail results. Since these attributes are boolean values do they need to be handled differently?
    – Scott Eddy
    Jun 17, 2014 at 13:15

2 Answers 2

1

This issue with my results were do to the fact mc_pin_system_avail was added after all products were created in the system. So to return the correct results I needed to edit every product and just save it to provide a default value for mc_pin_system_avail. Also I needed to add 'left' to make sure the values were left joined instead of inner joined.

array( array('attribute' => 'mc_pin_system_avail','eq'=> 1), array('attribute' => 'mc_pin_system','eq'=> 1) ),'left');
0

I need to have a little clarification on the selection you're expecting to occur. Are you expecting to have only items with mc_pin_system attribute and then only items that have mc_pin_system_avail set to True?

Setting it out visually in a truth table can help clarify what results you're expecting:

mps  mpsa
0    1
1    1

mps  mpsa
1    1

Similar situation in unrelated code I was working on yesterday to create separate related product types. The logic for handling selection of attributes ( addAttributeToFilter() ) from working code works as follows:

AND logic:

    /* Add filter to remove Spares and Options, from Related product display */
    $this->_itemCollection = $product->getRelatedProductCollection()
        ->addAttributeToSelect('required_options')
        ->addAttributeToSort('position', 'asc')
        ->addAttributeToFilter(
            array(
                array('attribute'=>'is_option', 'null' => 'true'),
                array('attribute'=>'is_option', 'eq' => '0')
            ), '', 'left'
        )
        ->addAttributeToFilter(
            array(
                array('attribute'=>'is_spare', 'null' => 'true'),
                array('attribute'=>'is_spare', 'eq' => '0')
            ), '', 'left'
        )
        ->addStoreFilter()
    ;
    /* End added filter */

OR Logic:

    /* Add filter to remove Spares and Options, from Related product display */
    $this->_itemCollection = $product->getRelatedProductCollection()
        ->addAttributeToSelect('required_options')
        ->addAttributeToSort('position', 'asc')
        ->addAttributeToFilter(
            array(
                array('attribute'=>'is_option', 'null' => 'true'),
                array('attribute'=>'is_option', 'eq' => '0'),
                array('attribute'=>'is_spare', 'null' => 'true'),
                array('attribute'=>'is_spare', 'eq' => '0')
            ), '', 'left'
        )
        ->addStoreFilter()
    ;
    /* End added filter */

Currently, your selection is using OR logic which will select mc_pin_system which can contain items having mc_pin_system_avail == 0 OR mc_pin_system_avail which can contain items having mc_pin_system == 0

$this->_productCollection
    ->addAttributeToFilter(
        array(
            array('attribute' => 'mc_pin_system','eq'=> 1),
            array('attribute' => 'mc_pin_system_avail','eq'=> 1)
        )
    );

To convert it to AND logic so only items with both mc_pin_system attributes set to 1 are selected

$this->_productCollection
    ->addAttributeToFilter(
        array('attribute' => 'mc_pin_system','eq'=> 1)
    )
    ->addAttributeToFilter(
        array('attribute' => 'mc_pin_system_avail','eq'=> 1)
    );
6
  • Yes I need the or logic so mc_pin_system_avail=1 mc_pin_system=0 or mc_pin_system=1 mc_pin_system_avail=0. array( array('attribute' => 'mc_pin_system_avail','eq'=> 1), array('attribute' => 'mc_pin_system','eq'=> 1) ),'left'); seems to have done the trick maybe because mc_pin_system_avail was added to the attribute sets later by the clients so there is a null value beacuse it has no default?
    – Scott Eddy
    Jun 17, 2014 at 15:35
  • Ok, yes, you have to include null results in your selection for attributes added after the fact. Adding the attribute doesn't add it to its parent item till the next save if a default was set. You'll notice I test for null on the attributes in my top samples, specifically because of this, for attributes that have No as their default value, but that haven't been updated since the attribute was created. And left is for left outer join for SQL SELECT Jun 17, 2014 at 15:43
  • left outer join sb left join Jun 17, 2014 at 15:50
  • ok it seems saving them is the only option the client actually edited the ones I thought I was getting by editing my query. I out put the query and it looks like this part is what's messing it up. The inner joins should be left joins.
    – Scott Eddy
    Jun 17, 2014 at 17:14
  • INNER JOIN catalog_product_entity_int AS at_mc_pin_system_avail_default ON (at_mc_pin_system_avail_default.entity_id = e.entity_id) AND (at_mc_pin_system_avail_default.attribute_id = '196') AND at_mc_pin_system_avail_default.store_id = 0 LEFT JOIN catalog_product_entity_int AS at_mc_pin_system_avail ON (at_mc_pin_system_avail.entity_id = e.entity_id) AND (at_mc_pin_system_avail.attribute_id = '196') AND (at_mc_pin_system_avail.store_id = 1)
    – Scott Eddy
    Jun 17, 2014 at 17:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.