Magento Tutorials Load A Category or Product by an Attribute

« Back to Magento Tutorials

New developers often ask me how to load a product by a particular attribute. This is quite easy to accomplish in Magento and can be done using Magento collections.

Load a Product by SKU

Unlike most product attributes, SKU is a static attribute. This means that instead of being stored in one of the products EAV tables, it is stored in the main product entity table (catalog_product_entity). This makes loading a product based on it's SKU much easier and efficient.

<?php

	$sku = 'my-product-sku';
	$product = Mage::getModel('catalog/product')->load($sku, 'sku');
	
	if ($product->getId()) {
		echo $product->getName();
	}
	else {
		echo 'Product not found with SKU of ' . $sku;
	}

The above code makes use of the load method, which is available for all EAV entities in Magento. By default this method takes two parameters: a value that's used to match the product and the field that the values is checked against. If the second parameter is empty, Magento will use the primary key, which is usually the model ID. By passing a static attribute (SKU is the only useful static attribute for this context), it is possible to load a product model on a different value.

Load a Product by an Attribute

The majority of product attributes that you work with in Magento will not be static attributes and their values will be separated across several different tables (for more information on this, see Magento Database Structure: EAV). Loading a product by a value that's stored like this is less efficient as several Magento tables will need to be joined to locate the product you are looking for. This doesn't mean that you shouldn't do it, it's just always good to be aware of such performance factors.

<?php

	// Instantiate a product collection object
	$products = Mage::getResourceModel('catalog/product_collection');
	
	// Select which fields to load into the product
	// * will load all fields but it is possible to pass an array of
	// select fields to load
	$products->addAttributeToSelect('*');
	
	// Ensure the product is visible
	$products->addAttributeToFilter('visibility', array('neq' => 1));
	
	// Ensure the product is enabled
	$products->addAttributeToFilter('status', 1);
	
	// Add Name filter
	$products->addAttributeToFilter('name', 'My Product Name');

	// Limit the collection to 1 result
	$products->setCurPage(1)->setPageSize(1);
	
	// Load the collection
	$products->load();
	
	if ($products->getFirstItem()) {
		$product = $products->getFirstItem();
		
		echo $product->getName();
	}
	else {
		echo 'No product exists with the name ' . $name;
	}

As you can see, the code above is a lot longer than the code we used to load by SKU, but hopefully you can see the power and flexibility of the Magento collection code. Line #17 is where the filter is added to filter by name, but the rest of the code is required to ensure that the product returned is a valid product.

If you are wondering what the SQL query the above generates, add the following line anywhere before line #23.

<?php
	
	// Print out the SQL query generated by the collection object so far
	echo $products->getSelect() . '<br/><br/>';

Loading a Category by an Attribute

Loading a category by an attribute is almost exactly the same. The reason for this is that both products and categories use Magento's EAV database structure and both extend from the same base classes, which provide the core collection functionality (as do the majority of Magento model's).

<?php

	// Instantiate a category collection object
	$categories = Mage::getResourceModel('catalog/category_collection');
	
	// Select which fields to load into the category
	// * will load all fields but it is possible to pass an array of
	// select fields to load
	$categories->addAttributeToSelect('*');
	
	// Ensure the category is active
	$categories->addAttributeToFilter('is_active', 1);
	
	// Add Name filter
	$categories->addAttributeToFilter('name', 'My Category Name');

	// Limit the collection to 1 result
	$categories->setCurPage(1)->setPageSize(1);
	
	// Load the collection
	$categories->load();
	
	if ($categories->getFirstItem()) {
		$category = $categories->getFirstItem();
		
		echo $category->getName();
	}
	else {
		echo 'No category exists with the name ' . $name;
	}

The main difference when working with categories is the resource model name (line #3) and the filter for the `is_active` attribute.

Hopefully you can see how flexible and powerful the Magento collection system is. I recommend that you print out the SQL query command for your collections so you can understand what Magento is doing in the background. Although Magento protects you from really needing to know this information, understanding it will make you a better developer and if you're like me, you'll find it interesting to disect the SQL!