Filter Products by Attribute on a Magento Cms Page
Yaroslav Rogoza Avatar

Ability to create pages with custom content is a great feature provided by Magento. You can easily create a new page for your store and add text, html, images, different widgets there. But sometimes people want to have something non-trivial on their pages. Usually it means that you need to operate some knowledge before you’ll get an appropriate result. In this article we would like to suggest you a simple solution on how to place a products list, prefiltered by some specific attribute, on your CMS page. The example below describes how to create a simple extension for this purpose.

Let’s call the extension Atwix_Cmsattr. First, you need to add the init file for you extension. The path is app/etc/modules/Atwix_Cmsattr.xml . The file’s content is:

<config>
    <modules>
        <Atwix_Cmsattr>
            <active>true</active>
            <codePool>local</codePool>
        </Atwix_Cmsattr>
    </modules>
</config>

The extension contains one block class and one model, therefore the config file, which you should have by the following path: app/code/local/Atwix/Cmsattr/etc/config.xml, is pretty simple and consists of a few records:

<config>
    <modules>
        <Atwix_Cmsattr>
            <version>0.1.0</version>
        </Atwix_Cmsattr>
    </modules>
    <global>
        <blocks>
            <atwix_cmsattr>
                <class>Atwix_Cmsattr_Block</class>
            </atwix_cmsattr>
        </blocks>
        <models>
            <atwix_cmsattr>
                <class>Atwix_Cmsattr_Model</class>
            </atwix_cmsattr>
        </models>
    </global>
</config>

After that, create the block class app/code/local/Atwix/Cmsattr/Block/List.php:

<?php
class Atwix_Cmsattr_Block_List extends Mage_Catalog_Block_Product_Abstract
{
    protected $_itemCollection = null;

    public function getItems()
    {
        $color = $this->getColor();
        if (!$color)
            return false;
        if (is_null($this->_itemCollection)) {
            $this->_itemCollection = Mage::getModel('atwix_cmsattr/products')->getItemsCollection($color);
        }

        return $this->_itemCollection;
    }
}

and the model class app/code/local/Atwix/Cmsattr/Model/Products.php:

<?php
class Atwix_Cmsattr_Model_Products extends Mage_Catalog_Model_Product
{
    public function getItemsCollection($valueId)
    {
        $collection = $this->getCollection()
            ->addAttributeToSelect('*')
            ->addAttributeToFilter('color', array('eq' => $valueId));
        Mage::getSingleton('cataloginventory/stock')->addInStockFilterToCollection($collection);
        return $collection;
    }
}

The next file is the most personal thing. You need the template file with your own mockup corresponding to your design. Here is an example for a simple list (app/design/frontend/base/default/template/atwix/cmsattr/list.phtml):

<?php $_items = $this->getItems() ?>
<div class="block">
    <div class="block-title">
        <strong><span><?php echo $this->__('Red Products') ?></span></strong>
    </div>
    <div class="block-content">
        <ol class="mini-products-list">
        <?php foreach ($_items as $_item): ?>
            <li class="item">
                <div class="product">
                    <a href="<?php echo $_item->getProductUrl() ?>" title="<?php echo $this->htmlEscape($_item->getName()) ?>" class="product-image"><img src="<?php echo $this->helper('catalog/image')->init($_item, 'thumbnail')->resize(50) ?>" width="50" height="50" alt="<?php echo $this->htmlEscape($_item->getName()) ?>" /></a>
                    <div class="product-details">
                        <p class="product-name"><a href="<?php echo $_item->getProductUrl() ?>"><?php echo $this->htmlEscape($_item->getName()) ?></a></p>
                        <?php echo $this->getPriceHtml($_item, true) ?>
                        <?php if ($this->helper('wishlist')->isAllow()) : ?>
                        <a href="<?php echo $this->getAddToWishlistUrl($_item) ?>" class="link-wishlist"><?php echo $this->__('Add to Wishlist') ?></a>
                        <?php endif; ?>
                    </div>
                </div>
            </li>
        <?php endforeach; ?>
        </ol>
    </div>
</div>

The last thing you need to do is to create a CMS page and insert the products list where you want to show it on the page. So, go to Admin->CMS->Pages->Add New Page. Fill the page with the necessary content and connect our products block anywhere in the content by putting the following string:

{{block type="atwix_cmsattr/list" name="cmsattr" template="atwix/cmsattr/list.phtml" color="26"}}

Note, that you need to pass the attribute value for color here. The product list on this page is filtered by this value. If you going to filter product by text attribute, such as “name” for example, you can pass the text value directly like name=”Apple”. But current example describes how to filter by attribute with type select. There are many ways to get value id from attribute’s value text. One of the simple (non programmatically) ways to do this is to inspect attributes values form using your browser. The example below describes how to do it within Google Chrome:

Also you can extend your model’s logic with the new method, which would transform attribute value text into it’s id, but this small article doesn’t describe how to do it :)
In the next articles we are going to tell how to use layered navigation (filters) for products on CMS pages.

Read also: Custom sort field for Magento products listing

Feel free to ask the questions and good luck in your coding experiments.

Also, don’t forget to read about importing product images from a URL in Magento 2 and the resource model for Magento product flat tables. Happy coding!

You may also want to read: