5
votes

I want to create different product views based on the attribute set the product belongs to: does Magento provide a way to do this?

- UPDATE -

Following dan.codes suggestion I've added

$update->addHandle('PRODUCT_ATTRIBUTE_SET_ID_'.$product->getAttributeSetId());

to Mage_Catalog_ProductController (I duplicated ProductController.php and put it in local/Mage/Catalog/controllers/).

Then I added this to catalog.xml

<PRODUCT_ATTRIBUTE_SET_ID_9> // PRODUCT ID of Book Attribute Set
    <label>Catalog Product View (Book)</label>
    <reference name="product.info">
        <block type="catalog/product_view_type_book" name="product.info.book" as="product_type_data" template="catalog/product/view/attribute_set/book.phtml">
            <block type="core/text_list" name="product.info.book.extra" as="product_type_data_extra"/>
        </block>
    </reference>
</PRODUCT_ATTRIBUTE_SET_ID_9>

just after

<PRODUCT_TYPE_virtual translate="label" module="catalog">
    <label>Catalog Product View (Virtual)</label>
    <reference name="product.info">
        <block type="catalog/product_view_type_virtual" name="product.info.virtual" as="product_type_data" template="catalog/product/view/type/virtual.phtml">
            <block type="core/text_list" name="product.info.virtual.extra" as="product_type_data_extra"/>
        </block>
    </reference>
</PRODUCT_TYPE_virtual>

I then created catalog/product/view/attribute_set/book.phtml, but it is not displayed in my product view page.

- UPDATE MAGENTO 1.5 -

I've noticed that the handler update has moved in the last Magento release.

$update->addHandle('PRODUCT_TYPE_'.$product->getTypeId());
$update->addHandle('PRODUCT_'.$product->getId());

is in Mage/Catalog/Helper/Product/View.php now.
I've tested and it still works great!

3
its working for me, maybe its what you are doing in your block, just to make sure the code is working change your xml to reference the root and set the template to something different and see if the page changes. `dan.codes

3 Answers

4
votes

No it doesn't but you can extend the functionality to do so by extending the _initProductLayout method in Mage_Catalog_ProductController under where the code is this

    $update = $this->getLayout()->getUpdate();
    $update->addHandle('default');
    $this->addActionLayoutHandles();

    $update->addHandle('PRODUCT_TYPE_'.$product->getTypeId());
    $update->addHandle('PRODUCT_'.$product->getId());

You could add

$update->addHandle('PRODUCT_ATTRIBUTE_SET_ID_'.$product->getAttributeSetId());

Then in your layout.xml you could have

<PRODUCT_ATTRIBUTE_SET_ID_IDHERE>
  <reference name="root">
            <action method="setTemplate"><template>template/path/here.html</template></action>
        </reference>
</PRODUCT_ATTRIBUTE_SET_ID_IDHERE>
2
votes

If in case you want to switch view.phtml based on the attribute set then here is what you need to do:

<PRODUCT_ATTRIBUTE_SET_ID_9>
    <label>Catalog Product View (Default)</label>
    <reference name="product.info">
        <action method="setTemplate"><template>catalog/product/custom-view.phtml</template></action>
    </reference>
</PRODUCT_ATTRIBUTE_SET_ID_9>

Just add this in your catalog.xml or local.xml
Hope this helps.
Thanks

2
votes

There is a good tutorial on this: http://magebase.com/magento-tutorials/creating-custom-layout-handles/

This uses following event: controller_action_layout_load_before

For this I set up in config.xml following

<events>
    <controller_action_layout_load_before>
        <observers>
            <mymodule>
                <class>mymodule/observer</class>
                <method>addAttributeSetHandle</method>
            </mymodule>
        </observers>
    </controller_action_layout_load_before>
</events>

And in Observer.php I will have

public function addAttributeSetHandle(Varien_Event_Observer $observer)
{
    $product = Mage::registry('current_product');

    /**
     * Return if it is not product page
     */
    if (!$this->isBookProduct($product)) {
        return;
    }

    $niceName = 'book';

    /* @var $update Mage_Core_Model_Layout_Update */
    $update = $observer
            ->getEvent()
            ->getLayout()
            ->getUpdate();
    $handles = $update->getHandles(); // Store all handles in a variable
    $update->resetHandles(); // Remove all handles

    /**
     * Rearrange layout handles to ensure PRODUCT_<product_id>
     * handle is added last
     */
    foreach ($handles as $handle) {
        $update->addHandle($handle);
        if ($handle == 'PRODUCT_TYPE_' . $product->getTypeId()) {
            $update->addHandle('PRODUCT_ATTRIBUTE_SET_' . $niceName);
        }
    }
}

protected function isBookProduct($product)
{
    if (null === $product || !($product instanceof Mage_Catalog_Model_Product)) {
        return false;
    }
    // TODO instead of hardcoded value we could use here something neat to get by name thru eav/entity_attribute_set model, some config value which hold that ID or use some other approach...
    $book_set_id = 9;

    if ($product->getAttributeSetId() != $book_set_id) {
        return false;
    }
    return true;
}

This makes possibility to use in layout xml following:

    <?xml version="1.0"?>
    <layout version="0.1.0">
        <PRODUCT_ATTRIBUTE_SET_book>
            <reference name="product.info">
                <action method="setTemplate">
                    <template>mymodule/book/product/view.phtml</template>
                </action>
            </reference>
        </PRODUCT_ATTRIBUTE_SET_book>
    </layout>