Magento – Filter collection by existence of attribute

attributescollection;

I'm working on an e-commerce site populated with products that depend heavily upon having well-populated spec sheets. Unfortunately quite a few of the products are somewhat less complete than I'd like, so I'm trying to find a way to get lists of products that have a given attribute but with no value.

So far I've got the following:

<?php
require_once('/app/Mage.php');
Mage::app();

$collection = Mage::getModel('catalog/product')->getCollection()
                ->addAttributeToSelect('name')
                ->addAttributeToSelect('noise_at_1m')
                ->addAttributeToSelect('noise_at_7m');

echo "<table><tr><td>Model name</td><td>Noise at 1m</td><td>Noise at 7m</td></tr>";
$numcomplete = 0;
$numhalfcomplete = 0;
foreach($collection as $_product){
    $name = $_product['name']; $noise1m = $_product['noise_at_1m']; $noise7m = $_product['noise_at_7m'];
    echo "<tr><td>$name</td><td>$noise1m</td><td>$noise7m</td></tr>";
    if(strlen($noise1m) > 1 &&  strlen($noise7m > 1)){$numcomplete++    ;}
    if(strlen($noise1m) > 1 XOR strlen($noise7m > 1)){$numhalfcomplete++;}
}
echo "</table>\n";
echo "<br>$numcomplete products with complete data\n";
echo "<br>$numhalfcomplete products with partially complete data\n";
echo "<br>" . (count($collection) - ($numcomplete + $numhalfcomplete)) . " products with no noise data at all";
?>

Which does exactly what it looks like – spits out a big ugly table with every product on the site along with whatever values are set for the attribute I'm searching. Not a big problem since the site only carries a few hundred products. Since it brings up every product in the site though I don't actually have a very good idea of how many products are actually supposed to be populated.

To try and get a better idea of how many products have missing data, I'd like to be able to filter the collection down to just products whose attribute sets include the attribute I'm checking. I don't need to be able to check multiple attributes in one shot since in this case although I'm checking two attributes, anything that has one will have the other. Anyway. I've tried swapping

$collection = Mage::getModel('catalog/product')->getCollection()
                ->addAttributeToSelect('name')
                ->addAttributeToSelect('noise_at_1m')
                ->addAttributeToSelect('noise_at_7m');

for

$collection = Mage::getModel('catalog/product')->getCollection()
                ->addAttributeToFilter('noise_at_1m','*')
                ->addAttributeToSelect('name')
                ->addAttributeToSelect('noise_at_1m')
                ->addAttributeToSelect('noise_at_7m');

I expected this to filter the collection to just products which had the attribute I'm looking for, regardless of whether it was set or what it was set to. Nope. This just empties the collection, so clearly I can't filter by a field like that.

Which leaves me with the simple question:

Is it possible to filter a collection to just products which have a given attribute, whether the value is set or not?

Best Answer

Say we have a newly created product eav attribute: xxx. It doesn't really matter how it's created. Let's say it is, and it's done correctly.

Now let's assume we've taken a product and from the backend we've set the Xxx input text to something, anything. So we have a single product that has the attribute "xxx" set.

How do I get all the product which don't have that attribute set?

// get all the product that DON'T have the attribute 'xxx' set yet
Mage::getModel('catalog/product')->getCollection()->addAttributeToFilter('xxx', array('null' => true), 'left');

// get all the product that DO have the attribute 'xxx' set
Mage::getModel('catalog/product')->getCollection()->addAttributeToFilter('xxx', array('notnull' => true), 'left');

The third param is "inner" by default. The row sum of these queries should be the number of products you have in DB, so these queries are - and should be - mutually exclusive.

Hope this helps.

Related Topic