Le Layout sur Magento
Le Layout est une partie vraiment importante que tout développeur Magento doit connaître.
De premier abord il n'est pas simple de comprendre le fonctionnement du layout et c'est bien là le but de cet article.
Mais pas seulement ! Je vais aussi vous donner quelques trucs pour maîtriser encore mieux le layout !
Le Layout c'est du XML.
La balise principale est layout
, quoi de mieux ?
Les handles
Le layout de Magento est vraiment très complet. On a des fichiers de plusieurs centaines de lignes parfois. Mais comment distinguer quelles parties du layout vont s'appliquer à notre page ?
Les handles sont des balises libres. Lors de son chargement Magento complète une liste de handles qui seront utilisés lors du rendu final.
Pour dire à notre action, dans notre contrôleur, d'utiliser les handles par défaut il faut utiliser la ligne de code suivante :
La méthode loadLayout()
appelle deux méthodes qui sont les méthodes qui ajoutent réellement les handles par défaut :
et
Pour une action qui serait jbh_foo/bar/baz
nous aurions les handles suivants :
-
default
: handle principal par défaut -
STORE_default
: handle du store (par défaut) -
THEME_frontend_default_default
: handle du thème (par défaut) -
jbh_foo_bar_baz
: handle de notre action
On peut changer le handle default
par autre chose si on le précise comme ceci :
Avant le chargement de ces layouts l'évènement controller_action_layout_load_before
est lancé par Magento. Donc si vous souhaitez ajouter un handle il faut le faire avant cet évènement.
Magento peut gérer des handles à l'infinie.
Attention cependant : L'ordre de traitement de ces handle a son importance ! Car on peut faire de la surcharge de name
et bien d'autres choses encore !
Dans le layout, on peut demander à charger un handle défini de la manière suivante :
C'est très pratique ! Et ça permet surtout de ne pas dupliquer de code !
Comment trouver le handle d'une page ?
Prenons par exemple la page de connexion dont l'URL est : https://example.org/customer/account/login
Il nous suffit de remplacer les /
par des _
:
customer_account_login
En règle générale :
- En premier c'est le nom de la route (et pas du module !)
- En deuxième c'est le nom du contrôleur
- En troisième c'est le nom de l'action
Les blocks
Le layout c'est plein de block
qui ont tous deux attributs principaux :
-
type
ouclass
: indique la classe PHP du block (par exemple :jbh_foo/bar
indique la classeJbh_Foo_Block_Bar
– à priori) -
name
: indique le nom du block dans le layout (doit être unique)
On peut ensuite trouver d'autres attributs tels que :
-
template
: indique le path du fichier template.phtml
utilisé par le block -
as
: indique le nom du block dans son parent -
translate
: indique les différentes balises qui peuvent être traduites (label
est la valeur la plus utilisée) -
output
: indique la méthode du block à utiliser pour forcer l'affichage de celui-ci -
parent
: indique le nom du block parent (surcharge le parent réel dans le XML) -
before
: indique la place du block dans son parent (si la valeur est-
alors le block sera ajouté tout au début de la liste des blocks enfants de son parent) -
after
: indique la place du block dans son parent (si la valeur est-
alors le block sera ajouté tout à la fin de la liste des blocks enfants de son parent). Cet attribut n'est pas traité sibefore
existe. Si la valeur est-
et qu'un block est généré ensuite avec unafter="-"
alors ce dernier prendra la place en fin de liste.
Surcharger un block
On peut surcharger un block dans le layout, pour changer son type par exemple !
Deux solutions :
- Changer le type directement dans le fichier
.xml
qui déclare le block. - Ajouter un nouveau block avec le même
name
.
La première solution a l'avantage de ne pas créer d'instance de block inutilisée. Cependant elle a le désavantage d'obliger (bien souvent) le développeur à copier le fichier .xml
du core dans son nouveau thème et à en modifier le contenu.
La seconde solution permet en fait d'écraser un block existant. Le problème dans ce cas c'est que lorsqu'on écrase le block, celui-ci disparaît du layout mais il reste dans son parent (sauf si on ajoute l'attribut parent
à notre nouveau block, auquel cas il y a aussi un écrasement). On perd également toutes les opérations effectuée sur le vieux block, ainsi que tous ces enfants (qui sont toujours dans le layout mais qui étaient dans le block qu'on tente de remplacer).
En conclusion il est plus simple d'utiliser la première méthode. Cependant la seconde méthode peut avoir un avantage si on souhaite surcharger un block simple (qui n'a pas d'enfants) et sur lequel il n'y a pas eu d'action
(voir plus bas « Les actions »).
Les références
Dans un handle
on peut récupérer un block en utilisant une référence.
Une référence c'est juste un rappel du block pour permettre l'appel à des actions ou l'ajout de blocks enfants.
Une référence peut être insérée à n'importe quel endroit dans le handle : dans un block ou même dans une autre référence.
Un seul attribut est nécessaire (et obligatoire) pour la balise reference
: l'attribut name
. Celui-ci indique le nom du block à utiliser en tant que parent pour tout ce qui est dans le noeud reference
en cours de traitement.
Par exemple pour faire une référence au content, pour y ajouter un block par exemple, sur toutes les pages (handle default
donc) :
Les actions
Les actions sont très pratiques ! On utilise le XML du layout pour appeler des méthodes d'un block !
(La principale action utilisée est celle qui consiste à changer le template d'un block.)
Une action
comprend 2 attributs :
-
method
: il est obligatoire, il indique la méthode du block à appeler (peut être une méthode magique ! si si;)
) -
block
: il est facultatif, il permet d'indiquer le block sur lequel l'action doit être appliquée.
Une action fait donc appel à une méthode de son block :
- soit le block parent dans le Layout
- soit le block précisé par l'attribut
block
Dans les deux cas il faut préciser (sauf s'il n'y en a pas) les paramètres de la méthode.
Pour cela il suffit de suivre une logique simple :
- Le premier paramètre sera le premier enfant de l'action
- Le second paramètre sera le second enfant de l'action
- etc.
Si bien que si nous avons par exemple la méthode suivante :
Nous aurons l'action ci-dessous :
Nous ne mettons pas de 4ème balise car nous ne voulons pas préciser de 4ème paramètre lors de notre appel.
D'ailleurs... ce 4ème paramètre c'est un tableau !
Pour les tableaux c'est un peu plus compliqué...
Notez que bien souvent le nom d'une balise correspond au nom de la variable en paramètre de la méthode, pour plus de clareté (et uniquement pour cette raison, sauf pour les tableaux ;)
).
Les tableaux en paramètre
Pour un tableau de valeurs (indexé) il faut faire :
Pour un tableau associatif il faut faire :
Et bien sûr on peut aller loin...
Et ainsi de suite !
Par contre à partir du second niveau vous ne pourrez plus faire de tableaux indexés.
Changer le template d'un block
Nous voulons par exemple changer le template de la page de login (template global).
D'abord il nous faut déterminer le handle de cette page le plus approprié. Le plus simple quand il faut modifier le template d'un block qui n'est que sur une seule page c'est d'utiliser le handle de l'action. Ici nous avons donc le handle suivant :
customer_account_login
Ensuite nous devons trouver le block sur lequel nous devons changer le template.
Comme nous voulons changer le template global, le block est root
.
Nous avons maintenant deux possibilités :
Soit on passe par une référence :
Soit on utilise l'attribut block
:
Il s'avère qu'il est d'ailleurs préférable de changer le template d'un block en utilisant l'attribut block
plutôt qu'en utilisant une référence car c'est moins coûteux en ressources : on fait une itération en moins dans la génération des blocks. (c'est peu certes, mais c'est par là que passe l'optimisation... aussi)
Ignorer un block
On voit de temps en temps une petite ligne qui ressemble à ceci :
Cette balise permet d'ignorer un block. Ici on ignore le block left
(la colonne de gauche).
Et il arrive assez fréquemment que le développeur se demande si le fait de mettre cette balise avant ou après la création d'un block aura un impact différent.
La réponse est non.
En effet, Magento utilise XPATH pour ignorer tous les noeuds et toutes les références aux noeuds dont le nom est indiqué dans l'attribut name
de tous les tags remove
du Layout.
Si vous ne voulez pas qu'un noeud soit finalement ignoré il faut réussir à supprimer le noeud remove
qui le « supprime » ! (logique !)
(Sinon vous pouvez aller voir du côté du module Layout UnRemove de Alan Storm.)
La balise remove
accepte l'attribut acl
pour indiquer si on ignore ou non ce block dans le cas d'un layout admin. L'attribut prend la valeur du droit nécessaire pour afficher le block comme par exemple :
Si l'administrateur connecté a le droit jbh_foo/bar
alors le block ne sera pas ignoré.
A noter aussi qu'on peut inhiber l'action du remove sur un block en définissant l'attribut ignore
de celui-ci !
Ce block ne pourra donc pas être supprimé via remove
. Attention par contre... vu qu'on ne peut pas ajouter un attribut à un block déjà existant (via une référence par exemple) cette manipulation implique que le block ne sera jamais ignoré.
Le fichier local.xml
(dans design/../layout/
)
Surprise ! Ce fichier est toujours parsé en dernier ! Donc si vous souhaitez faire de la mise à jour pour un thème sans rien en particulier vous pouvez utiliser ce fichier.
C'est bon à savoir non ?
Avec lui, plus besoin de faire un module pour « nettoyer » votre thème :)
Un recherché remplacé ?
Oui ! Magento effectue un str_replace
sur tout votre XML comme ceci :
{{baseUrl}}
devient l'URL non sécurisée de votre store{{baseSecureUrl}}
devient l'URL sécurisée de votre store
Les updates
Un update c'est simplement un bout de XML ajouté au layout qui sera traité de la même façon que tous les fichiers .xml
de votre thème.
Le tag update
Il ne peut être qu'un enfant d'un handle, sinon il ne sera pas pris en compte.
Il doit comporter un seul attribut : handle
.
Cet attribut indique le nom d'un autre handle qui doit être pris en compte dans le layout.
Vous pouvez par exemple vouloir appliquer le handle customer_account
à votre nouvelle page pour qu'elle s'intègre parfaitement dans la partie "Mon Compte" du client :
Vous pouvez également utiliser cette technique pour éviter de dupliquer un gros bout de layout que vous voudriez réutiliser !
Des updates en base de données
Les Widgets utilisent la base de données pour ajouter des updates sur le layout.
Il nous est possible de faire de même si on le souhaite en utilisant les deux tables core_layout_link
et core_layout_update
.
Désactiver le module des Widgets n'empêchera pas Magento de faire une requête SELECT
par handle par page.
Donc si vous n'avez pas de cache, sachez que Magento fait au minimum 4 requêtes pour récupérer les possibles layout updates en base de données à chaque chargement.
A savoir que la sauvegarde d'un seul Widget invalidera les caches suivants :
- Le cache « Blocks HTML output » (
block_html
) - Le cache « Layouts » (
layout
)
Merci les widgets ! (à utiliser avec parcimonie donc...)
Conclusion
Vous maîtrisez maintenant le layout sur Magento ! Au moins vous avez les connaissances... Vous savez comment créer, modifier, supprimer tout ou partie du Layout. Il ne vous manque plus que la pratique !
A présent n'hésitez surtout pas à laisser un commentaire sur vos astuces bien à vous ;) Ou simplement pour réagir à cet article !