Magento templates

Les Templates et le Design Magento

Https + cache Magento + Internet Explorer = Pas d'images

Magento propose nativement un système de cache avancé afin d'afficher le contenu des templates plus rapidement. La configuration par défaut de ce cache peut cependant poser problème dans certaines situations.

Récemment, nous avons eu le problème de certaines images qui ne s'affichait pas dans le menu du haut lorsque nous passions d'une page http à une page https et ce uniquement sur Internet Explorer. Les images dans ce menu restait en effet avec une url non sécurisé (http). Celà ne plait pas trop à Internet Explorer qui par défaut n'affiche pas le contenu non sécurisé sur une page sécurisé. On a en effet le message suivant lorsque certaines images ont une adresse http alors que la page est en https:

Internet Explorer Security Warning

Le block affichant le menu avec les catégories était mis en cache et son cache n'était pas regénéré si l'on passait d'une page http à une page https. Ce qui explique pourquoi les images restaient avec une adresse http sur un page https.

Pour corriger cela, il faut réécrire la méthode getCacheKey de la classe Mage_Catalog_Block_Navigation. Il faut en effet inclure dans la clé du cache un paramètre indiquant si l'url est en https ou en http. Le cache sera alors différent pour ces 2 types de pages. Ce paramètre est ajouté avec la méthode getSkinUrl

Le code par défaut de getCacheKey

public function getCacheKey()
{
    return 'CATALOG_NAVIGATION_' . Mage::app()->getStore()->getId()
        . '_' . Mage::getDesign()->getPackageName()
        . '_' . Mage::getDesign()->getTheme('template')
        . '_' . Mage::getSingleton('customer/session')->getCustomerGroupId()
        . '_' . md5($this->getTemplate() . $this->getCurrenCategoryKey());
}

est donc remplacé par le code suivant

public function getCacheKey()
{
    return 'CATALOG_NAVIGATION_' . Mage::app()->getStore()->getId()
        . '_' . Mage::getDesign()->getPackageName()
        . '_' . Mage::getDesign()->getTheme('template')
        . '_' . Mage::getSingleton('customer/session')->getCustomerGroupId()
        . '_' . md5($this->getTemplate() . $this->getCurrenCategoryKey())
        . '_' . md5($this->getSkinUrl()); /*** FIX IN THIS LINE ***/
}

Et voilà, vous pouvez désormais utiliser sereinement https sur Internet Explorer

Pour plus d'infos concernant la gestion des caches sous Magento vous pouvez consulter cet article.

Prototype et jQuery dans Magento

Comme vous le savez peut-être déjà, le framework Javascript Prototype est inclus par défaut dans magento. Combiné avec script.aculo.us, c'est un outil puissant pour programmer les interactions du côté client. Il fournit aussi un framework Ajax, ce qui rend n'importe quelle requête ajax plus facile à réaliser.

Beaucoup de templates magento utilisent les fonctionnalités de Prototype, pour par exemple, afficher/masquer des éléments selon le choix de l'utilisateur ou pour afficher des messages d'erreur avec un sympathique effet 'fade'.

Mais Prototype n'est pas la seule bibliothèque Javascript à proposer un ensemble de fonctions utiles. JQuery est une autre bibliothèque très populaire – très légère (19KB dans sa version minimisée et compressée), simple à utiliser et, à dire vrai, ma favorite. Créée en 2006, elle a désormais une large communauté et un énorme ensemble de plugins.

Cependant, est ce une bonne idée d'utiliser ces deux bibliothèques sur un site magento? A mon avis, non. En tout cas dans la plupart des cas. Pourquoi? Il y a plusieurs raisons :

  • Elles fournissent les mêmes fonctionnalités. Ce qui est donc possible avec l'une l'est aussi avec l'autre.
  • Inclure plus de bibliothèques implique augmenter le nombre de données à télécharger par le navigateur et ralentir le chargement des pages
  • Elles utilisent une structure commune ce qui peut engendrer des conflits

Néanmoins, dans certains cas vous pourriez être amené à inclure jQuery dans votre site magento. Par exemple, vous avez besoin d'utiliser une bibliothèque JavaScript supplémentaire qui a été crééez en tant que plugin jQuery. Comment pouvons nous alors forcer Prototype et jQuery à fonctionner ensemble sans conflit ? Premièrement, vous devez télécharger une version récente de jquery (la version actuelle est la 1.3.2) et la placer dans le dossier /js/jquery. Vous devez alors l'inclure dans toutes vos pages magento – la façon la plus logique de faire cela est de placer le code suivant dans la section <block type="page/html_head"> du fichier /app/design/frontend/.../.../layout/page.xml:

<action method="addJs"><script>jquery/jquery-1.3.2.min.js</script></action>

Maintenant, vous devez éviter les conflits avec Prototype – elles utilisent toutes deux la notation $ (dans jQuery c'est un raccourci pour jQuery et dans Prototype c'est un alias pour la fonction getElementById). Heureusement, il existe un méchanisme dans jQuery pour remplacer la fonction $ : jQuery.noConflict(). Vous pouvez mettre un tel code a la fin de votre fichier jquery-1.3.2.min.js :

var $j = jQuery.noConflict();

et désormais, vous devez utiliser $j à la place de la fonction $ (ou, si vous préférez, vous pouvez toujours utiliser jQuery). Prenez alors bien soin de modifier tous vos appels de $ dans vos plugins jquery (mais il y a déjà beaucoup de plugins qui incluent le code jQuery.noConflict()).

Et cela serait tout s'il n'y avait pas un navigateur qui pose encore problème pour faire cohabiter Prototype et jQuery. Étonnamment, il ne s'agit pas d'Internet Explorer. C'est Firefox 2. Il retourne des erreurs et refuse d'exécuter le JavaScript. Bien sûr, il existe de nouvelles version de Firefox où le problème n'apparaît plus, mais il existe encore un petit pourcentage d'internautes qui utilisent Firefox 2 et qui voudraient dépenser de l'argent dans votre magasin. Heureusement, il existe un moyen simple pour résoudre ce problème. Vous devez inclure le fichier jQuery avant Prototype. Vous avez alors quelque chose comme ça dans page.xml:

<action method="addJs"><script>jquery/jquery-1.3.2.min.js</script></action>
<action method="addJs"><script>prototype/prototype.js</script></action>

Et maintenant vous pouvez oublier les conflits et apprécier ces superbes bibliothèques fonctionnant ensemble.

Traduction par Laurent Clouet

Les Thèmes sous Magento

Un thème est n'importe quelle combinaison de fichier, de template et/ou de skin qui créent l'expérience visuelle de votre site e-Commerce. Magento a la capacité de charger des thèmes multiples en même temps, et distingue donc les thèmes sous deux catégories

  • Le thème par Défaut
    Chaque interface vient avec un thème appelé par "défaut" qui est le thème principal d'une interface. Quand vous assignez une interface à votre boutique, l'application recherche automatiquement ce thème par "défaut" et charge ce thème dès l'entrée sur la boutique. Afin de personnaliser la conception de votre boutique, vous pouvez éditer ou modifier ce thème, ou créer un autre thème et le charger à côté de celui par défaut. Le thème par défaut doit contenir toutes les Paginations requises, les Templates et les Skins pour que votre boutique soit exempte d'erreurs et est par conséquent le thème prioritaire dans la hiérarchie de chargement des thèmes.

  • Les autres thèmes
    Selon vos besoins, un autre thème peut contenir autant de fichiers que bon vous semble. Ce type de thème est destiné à apporter des modifications provisoires, vous pouvez créer une présentation saisonnières sans devoir créer un nouveau thème par défaut complet avec seulement quelques images et en mettant à jour une partie du CSS, vous pouvez facilement transformer votre boutique en véritable stand de Noël pour une courte durée.

Maintenant jetons un coup d'œil aux composants d'un thème :

  • (Layouts) Paginations
    Des fichiers XML basics définissent la pagination des blocs pour les différentes pages, aussi bien que contrôler les informations des balises META et l'encodage des caractères dans la page. Les fichiers de pagination sont séparés sur la base d'un par module, chaque module apporte avec lui son propre fichier de pagination.

  • Templates
    Les Templates sont des fichiers PHTML qui contiennent des marqueurs (X)HTML et qui sont nécessaires à PHP pour créer une présentation visuelle logique des informations et des fonctionnalités.

  • Skins
    Les Skins sont des Block spécifiques de Javascript, de CSS et de fichiers Images qui complètent votre code (X)HTML. Quels sont ces blocs me direz-vous? Bonne question, et ne vous inquiétez pas, nous avons presque fini de définir les composants de Magento.

Les Blocks

Les Blocs sont un moyen par lequel Magento distingue la gamme de fonctionnalités dans le système et crée une façon modulaire pour gérer cette gamme d'un point de vue visuelle et à la fois fonctionnelle. Il existe deux types de blocs et ils travaillent ensemble à créer la sortie visuelle.

  • Blocs Structuraux
    Ce sont des blocs dont l'objectif unique est de définir la structure visuelle d'une page de votre boutique. Les exemples seraient l'en-tête, la colonne de gauche, la colonne principale et le pied de la page.

Structure des blocs d'une page dans Magento
#Header
#Left
#Main
#Footer

  • Les Infoboxes
    Ce sont des blocs qui affichent le contenu réel à l'intérieur de chaque bloc structurel. Chaque éléments représentent une fonctionnalité dans la page et ils utilisent des templates pour générer du code (X)HTML à insérer dans le bloc structurel parent. Les exemples sont la liste des catégories, le mini panier, les tags de produit et la liste des produit, le comparateur...

#Header
Category
List
Callout
Product
Tags
Compare
products
Product Listing
Sub Category List
Newsletter
Signup
Footer Links
Callout

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 !

Comprendre les Templates standard de Magento

Le système de templates Magento vous permet de créer facilement des éléments HTML/CSS personnalisés tout en respectant l'architecture et le design Magento.
Cependant, dans certains cas, il peut être judicieux d'utiliser les Templates standard (Default Template). Cela vous permettra de gagner du temps à l'intégration de nouveaux élements HTML au sein des fonctionnalités de Magento.

Par exemple, regardons le contenu de ce répertoire dans l'installation standard de Magento : app\design\frontend\default\default\template\page.
Nous trouvons ici les gabarits (templates) d'une page classique : 1column.phtml, 2colums-left.phtml, 2colums-right.phtml ou 3colums.phtml. Tous contiennent la même structure page (concentrons-nous sur la section 'body') :

<div class="wrapper">

<!-- start header -->
        <div class="header">
            ...
        </div>
<!-- end header -->

<!-- start middle -->
        <div class="middle-container">
            ...
        </div>
<!-- end middle -->

<!-- start footer -->
        <div class="footer-container">
                <div class="footer">
                    ...
                </div>
        </div>
<!-- end footer -->

</div>

Ils diffèrent uniquement dans la partie <div class=”middle-container”>, où le code HTML de mise en page est défini.
Comme vous pouvez le voir, il s'agit là d'une manière tout à fait classique de contruire des page – en-tête, corps, pied de page.
Ainsi, dans la majortité des cas, vous pouvez utiliser ces gabarits sans changer de code HTML et vous borner à créer votre habillage CSS (skin) qui adaptera le rendu de votre page à vos besoins.
Bien sûr, plus un gabarit est complexe, plus il sera difficle de l'adapter, mais vous pouvez commencer par travailler sur un gabarit standard (default magento template) et ne modifier que ce dont vous avez besoin.

Traduction par Benjamin Bellamy

Afficher un block BestSellers (meilleures ventes) sur la page d'accueil de votre site Magento

Une des questions qui vient souvent lors de la mise en place d'un site Magento est la suivante : comment afficher les BestSellers (meilleures ventes) sur la page d'accueil ?

En effet, Magento - dans sa version actuelle du moins - ne propose pas nativement cette fonctionnalité.

Pour autant, si ce manque peut paraître étrange pour une solution e-commerce, il n'est en rien bloquant. Bien au contraire, il va nous permettre de nous rendre compte de la (relative) facilité avec laquelle il est possible de créer de nouveaux blocs, ou du moins de l'évolutivité de l'architecture de Magento.

  1. Récupérez les données

    C'est sûrement la partie la plus compliquée car elle nécessite de maîtriser le modèle objet de Magento.
    À partir du moment où vous savez où aller chercher les données (ici les produits vendus) et comment les requêter (ici en les triant par nombre de ventes décroissantes), obtenir les informations voulues est très simple et tient sur une seule ligne (en fait plusieurs pour un souci de lisibilité).

    $_productCollection = Mage::getResourceModel('reports/product_collection')
        ->addAttributeToSelect('*')
        ->addOrderedQty()
        ->setOrder('ordered_qty', 'desc');

  2. Créer votre block BestSellers

    Respectez le modèle MVC : dans Magento comme dans Zend, chaque objet a sa place et son rôle.
    Créez vos objets métier :
    Typiquement, dans un fichier app/code/local/ma_librairie/Bestseller/Model/Bestseller.php vous définissez votre classe métier qui contient la règle de calcul (ici : afficher les produit nombre de vente décroissante).
    Puis dans app/code/local/ma_librairie/Bestseller/Block/Bestseller.php vous étendez la classe Mage_Core_Block_Template qui se chargera de transmettre proprement les données au block d'affichage.
    Enfin dans app/design/frontend/mon_theme/default/template/catalog/product/view/bestseller.phtml affichez le contenu du block.
    Bien entendu, ces objets doivent être déclarés dans les fichiers XML adéquats.

  3. Affichez votre block

    Il ne vous reste plus qu'à placer votre block dans votre layout actif.
    Pour ce faire, vous pouvez soit modifier votre fichier XML de layout, soit effectuer l'ajout dans le back-office de configuration Magento sur votre page CMS d'accueil.

Pour plus d'information sur les Templates, consultez le billet Créer un template pour son site Magento.

Créer un template pour son site Magento

Créer un template pour son site Magento est une étape incontournable dans la mise en place en place de sa boutique en ligne. En effet, la charte graphique d'une e-Boutique est aussi importante que la vitrine d'un magasin : il s'agit de la première chose que verra le chalant qui passe devant par hasard.
C'est votre vitrine qui retiendra un client potentiel ou qui, au contraire, l'incitera à partir.

(Il existe bien entendu d'autre moyens de faire venir des prospects directement au coeur de votre boutique, via les moteurs de recherche notamment, mais ceci fera l'objet d'autres billets.)

Fort de ce constat, tout le système de gestion du design Magento a été conçu et pensé afin de vous permettre d'achalander au mieux les pages de votre site Magento, de les organiser et de les décorer comme bon vous semble. (Et bien entendu sans faire de développements spécifiques qui interdiraient par la suite de bénéficier des mises à jour de Magento.)

Afin de personnaliser la présentation d'un site Magento, trois types d'objets sont mis en oeuvre, abondamment cités dans les documentations, forums de discussions et autres wiki :

  1. les templates (gabarits ou modèles)
  2. les skins (revêtements)
  3. les layouts (agencements, dispositions)

La compréhension de ces trois types d'objets est primordiale afin de comprendre comment penser votre boutique en ligne.

Les Templates

Les templates (gabarits ou modèles) ne sont ni plus ni moins qu'un ensemble des blocks qui composent votre boutique.

Ce sont ces blocks qui vont par exemple :

  • afficher le détail d'un article,
  • afficher le contenu du panier client,
  • afficher le promo du mois,
  • afficher les menus de navigation,
  • afficher du contenu telles que les conditions générales de vente,
  • et caetera.

Magento fournit un template par défaut qui contient toute une série de blocks standard. Il est possible, par un système d'héritage, de compléter, surcharger, modifier des blocks, d'en créer de nouveaux, et caetera.
En outre, Magento étant basé sur la framework Zend, lui même MVC, les règles métier relatives à l'affichage de ces blocks sont définies ailleurs, permettant ainsi une parfaite indépendance de votre charte graphique vis à vis du coeur du système.

Les Skins

Les skins (revêtements) renferment l'ensemble des feuilles de style CSS de votre site et décrivent avec quelle mise en forme (couleurs, images, polices de caractères...) les blocks de templates vont être affichés. Séparées des templates, il devient ainsi excessivement aisé de modifier un style graphique d'affichage sans devoir modifier les blocks.

Changer tout ou partie de la charte graphique peut ainsi être facilement réalisé, par exemple :

  • pour une partie du site (catégorie spécifique, déstockage...)
  • pour une période donnée (Noël, soldes...),
  • pour une catégorie particulière d'internaute (comités d'entreprises, VIP...),
  • et caetera.

Les Layouts

Les layouts (agencements, dispositions) quant à eux vont définir quels blocks va s'afficher sur quelle page (page catalogue, page produit, page de paiement, page de compte client...) et en définir les attributs. Il ne s'agit donc ni plus ni moins que de la définition de la structure générale de votre site. Là encore, un layout standard est proposé, celui-ci étant très facilement personnalisable.