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!
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>
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
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>