Magento types produits

Magento : Le bloc "product_type_data"

Comme chacun le sait, Magento est extensible de façon modulaire, et il est possible de construire de nouvelle fonctionnalités assez aisément tout en se reposant sur de l'existant.

Ainsi, il est relativement simple de composer dans un nouveau module Magento une page réutilisant plusieurs block standards, par le biais, par exemple, d'un nouveau contrôleur. Prenons l'exemple d'une fonctionnalité de "Quicklook", c'est à dire un aperçu d'un produit permettant de l'intégrer au panier rapidement via des requêtes Ajax.

La logique est donc assez différente de la page produit standard, toutefois, certains éléments de celle-ci pourraient néanmoins figurer sur notre aperçu, afin de factoriser le plus de choses possibles, notament le block permettant la sélection des options.

Or, un site Magento peut être pourvu d'un catalogue comportant des produits de natures différentes : des produits simples, des produits configurables, des produits groupés, etc.. On s'attend donc à devoir contrôler le type du produit afin de pouvoir importer le block correspondant. Toutefois, si l'on jette un oeil au template de la vue produit standard ("catalog/product/view.phtml"), on peut remarquer qu'en lieu et place de tout celà, on trouve un simple :

$this->getChildHtml('product_type_data');

Intéressant ! Ce block ferait tout le travail à notre place ?

C'est effectivement le but, mais tout n'est pas si simple : ce block est introuvable dans le design par défaut, et son utilisation au sein d'un template executé via le contrôleur fourni dans un module autre que "catalog" ne fonctionne pas. Bon nombre de questions fusent à ce sujet dans les différents forums communautaires, et des solutions de contournement sont bien souvent utilisées, comme par exemple, inclure directement le block "configurable", ce qui est génant pour supporter les différents types de produits possibles.

La raison : le layout correspondant au module ne donne aucune indication sur le block "product_type_data". Si l'on observe le layout de catalog (catalog.xml), on trouve ceci :

<PRODUCT_TYPE_simple>
        <reference name="product.info">
                <block type="catalog/product_view_type_simple" name="product.info.simple" as="product_type_data" template="catalog/product/view/type/simple.phtml"/>
        </reference>
</PRODUCT_TYPE_simple>
<PRODUCT_TYPE_gift>
        <reference name="content.info">
                <block type="catalog/product_view" name="product.info" template="catalog/product/giftview.phtml" />
                <block type="catalog/product_view" name="product.info.preview" as="preview" template="catalog/product/view/preview.phtml"/>
        </reference>
</PRODUCT_TYPE_gift>
<PRODUCT_TYPE_configurable>
        <reference name="product.info">
                <block type="catalog/product_view_type_configurable" name="product.info.configurable" as="product_type_data" template="catalog/product/view/type/configurable.phtml"/>
        </reference>
</PRODUCT_TYPE_configurable>
<PRODUCT_TYPE_grouped>
        <reference name="product.info">
                <block type="catalog/product_view_type_grouped" name="product.info.grouped" as="product_type_data" template="catalog/product/view/type/grouped.phtml"/>
        </reference>
</PRODUCT_TYPE_grouped>

Ces quelques blocks XML définissent des "handles" customs, comparables à ceux qu'utilisent automatiquement les actions d'un contrôleur. On a donc un "handle" par type de produit, présentant chacun un block appelable via l'alias "product_type_data" mais fixant chacun un template adapté pour la mise en forme du contenu de ce block selon le type du produit.

Dernier problème : contrairement aux handles liés aux actions, qui sont automatiquements associés grace à une convention de nommage, ces handles supplémentaires ne seront pas interpretés. Comment donc se fait-il que cela fonctionne pour le module Catalog ?

Pour le comprendre, jettons un oeil au contrôleur principalement interessé, le ProductController ("/app/code/core/Mage/Catalog/controllers/ProductController.php"). Ce controller est généralement sollicité via l'action "view", c'est donc la méthode viewAction qui va nous interesser.

Dans celle ci, on va pouvoir trouver un appel à la méthode _initProductLayout, avec le produit passé en paramètre (ligne 125). Et dans l'implémentation de cette dernière, on trouve enfin ce qui nous interesse vers la ligne 94 :

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

Cette ligne déclare donc un handle supplémentaire dont le nom dépend du type du produit. Cela signifie que parmi tous les handles qui figurent dans le layout catalog.xml, on en interprètera qu'un : celui qui correspond au type du produit.

Voilà comment le block alias "product_type_data" est construit de façon à pointer vers un et un seul block adapté au type du produit à utiliser.

Vous pouvez donc reproduire ce principe dans vos modules spécifiques, et ainsi utiliser des inclusions génériques comme "product_type_data" dans vos templates. Pensez juste, notament, à changer le nom des handles si vous décidez d'utiliser des templates différents, ou si vous changez le block de réference, etc.. sinon vos changements risquent d'être pris en compte aussi par la fiche produit d'origine car les handlers de catalog auront été remplacés par les votres !