Les améliorations de JLayout pour Joomla!
From Joomla! Documentation
Cet article vous présente les nouvelles fonctionnalités de JLayouts
dans Joomla! 3.2.
La plupart des changements ont pour objectif d'améliorer la flexibilité du système pour les développeurs d'extensions tierces.
Un peu d'histoire
Prenons un exemple : vous avez des articles contenant des tags, mais des tags sont également présents dans vos contacts, vos catégories...
Avec l'ancien système de template et donc antérieur à JLayouts
(essentiellement ce que nous continuons d'utiliser pour les vues), il fallait copier/coller un même HTML dans l'ensemble des rendus où vous souhaitiez afficher vos tags. Ce n'est en fait pas très compliqué, n'est-ce pas ? Ok, mais admettons que quelqu'un opère une correction de bug pour le contenu mais, oublie de le faire pour les catégories, ou encore que quelqu'un ajoute une fonctionnalité intéressante, mais uniquement pour les contacts... C'est alors que les problèmes commencent et que le système devient difficile à gérer.
Yannick Gaultier a contribué à JLayouts
afin de résoudre ce problème. Un système simple et génial basé sur un concept de réutilisation de parties de codes vous permettant un rendu HTML à partir de données objets/arrays.
Les avantages quant à l'utilisation des rendus (layouts)
Grâce au système de JLayout, vous pouvez afficher les tags d'un élément avec :
echo JLayoutHelper::render('joomla.content.tags', $itemTags);
Cela va dans les faits permettre d'afficher les éléments du fichier situé dans /layouts/joomla/content/tags.php
en passant $itemTags
comme paramètre pour un usage interne. Ce que nous faisions dans les modules, mais d'une manière standard. La seule exigence est que l'objet $itemTags
partage la même structure pour tous les éléments.
Alors, quels sont les avantages ?
La réutilisation
Il nous faudra gérer un unique rendu, ainsi les designers n'auront à personnaliser qu'un seul affichage.
Séparer les données du design
Un autre avantage des JLayouts
est de devenir un véritable nouvel outil pour les développeurs en séparant le code HTML du PHP. Dans un monde idéal, 100 % des balises d'une page devraient pouvoir être substituées par un concepteur/développeur sans avoir à modifier le noyau Joomla. Cela signifie que si vous chargez un fichier JS, vous devriez le faire dans un endroit où le concepteur pourra le substituer s'il décide de ne pas utiliser votre JS, mais de le remplacer par une autre bibliothèque. C'est en fait un des plus gros problèmes que nous ayons dans Joomla! et la raison pour laquelle la plupart des concepteurs de sites ont pris peur après avoir tenté de collaborer pendant un certain temps.
Une intégration aisée dans 2.5.x
Le système de rendu ne représente que quatre fichiers. Vous pouvez les inclure à votre bibliothèque pour une compatibilité sous 2.5 et/ou les étendre avec vos propres classes.
Le précédent système JLayout
Avec le système JLayout précédent, un appel tel que celui-ci :
$layout = new JLayoutFile('joomla.content.tags');
$layout->render($itemTags);
Aurait cherché le rendu dans :
[0] => templates/mytemplate/html/layouts [1] => layouts
Cool ! Cela signifie que je peux le substituer. Mais également, vous pourriez forcer le dossier dans lequel vous souhaitez charger les rendus grâce à :
$layout = new JLayoutFile('joomla.content.tags', JPATH_SITE . '/components/com_mycomponent/layouts');
$layout->render($itemTags);
Ce qui permettrait de chercher les rendus dans :
[0] => templates/mytemplate/html/layouts [1] => components/com_mycomponent/layouts
Super, cela reste substituable !
Nouvelles exigences
Avec le précédent système de rendu, nous avions encore quelques problèmes :
- Les développeurs qui veulent utiliser les rendus dans leurs propres composants doivent spécifier le chemin de ces rendus pour chaque requête ou créer leurs propres classes étendues.
- Qu'advient-il si un concepteur souhaite un affichage des tags différent dans la vue de blog de celui de la vue de catégorie ?
- Comment un concepteur de site peut-il personnaliser le rendu d'un champ pour un composant spécifique ?
Dans le cadre de mon activité professionnelle j'ai dû faire face à ces problèmes et c'est à partir de ce moment que j'ai commencé à améliorer le système. Certains avaient des solutions "drastiques" avec l'utilisation de l'ancien système, mais je souhaitais un système automatisé simple qui fonctionnerait également pour des solutions complexes.
Nouvelles fonctionnalités
Suite à ma proposition initiale, la magie Joomla! a opéré et nous avons reçu de nombreuses suggestions supplémentaires. Le résultat final est un système qui s'est avéré nettement supérieur à ma proposition initiale. C'est la magie de l'open source.
Comme indice sur les nouvelles fonctionnalités, voici désormais un exemple d'appel aux rendus :
$layout = new JLayoutFile('joomla.content.tags', null, array('debug' => true, 'client' => 1, 'component' => 'com_tags'));
La substitution d'affichage de composant
Un des changements est que désormais le système recherche automatiquement les rendus du composant concerné.
Maintenant, la même requête que celle utilisée précédemment :
$layout = new JLayoutFile('joomla.content.tags');
$layout->render($itemTags);
Va automatiquement rechercher les rendus dans ces dossiers (affichage par ordre de priorité) :
[0] => templates/mytemplate/html/layouts/com_mycomponent [1] => components/com_mycomponent/layouts [2] => templates/mytemplate/html/layouts [3] => layouts
Cela signifie que vous pouvez utiliser les affichages standards, les substituer au niveau du composant et remplacer la substitution du composant au niveau du template.
Dans notre exemple, un développeur peut personnaliser la façon dont seront affichés les tags dans son composant et un concepteur de site pourra substituer la façon dont les tags s'afficheront dans ce composant.
Forcer un composant
L'exemple précédent détecte automatiquement le composant lorsque le rendu a été appelé. Mais que se passe-t-il si je veux que mes tags s'affichent de la même façon que dans com_tags ? Cela est également possible avec cet exemple d'appel :
$layout = new JLayoutFile('joomla.content.tags', null, array('component' => 'com_tags'));
Forcer le client
Un autre des éléments que le système détecte désormais automatiquement est le type de client. Cela signifie que si vous êtes sur le frontend, il recherchera les rendus de frontend.
Mais je veux que mes tags en backend aient le même affichage que le com_tags du frontend ! Cela est possible grâce à cet exemple d'appel :
$layout = new JLayoutFile('joomla.content.tags', null, array('client' => 0, 'component' => 'com_tags'));
Le paramètre client accepte ces valeurs :
- 0, 'site' > frontend
- 1, 'admin' > backend
Ajouter "include paths"
Disons que vous vous retrouvez avec des dossiers personnalisés contenant les rendus, mais que vous ne souhaitez pas tous les stocker. Par exemple, vous ne souhaitez ajouter qu'un dossier dans lequel Joomla! devra chercher les rendus et s'il ne les trouve pas, charger les rendus standard. Par exemple, dans ma société, nous avons une bibliothèque contenant nos affichages personnalisés et partagés pour tous nos composants.
Ceci peut se faire avec ce nouvel appel :
$layout = new JLayoutFile('joomla.content.tags');
$layout->addIncludePaths(JPATH_LIBRARIES . '/hacknsa');
Cela va ajouter /libraries/hacknsa au plus haut niveau de la recherche de rendus (priorité maximale). Cette méthode accepte également un array (arrangement ordonné de données variables) des chemins. Dans un array, souvenez-vous que le dernier aura la plus haute priorité.
Les suffixes
Une autre proposition (celle-ci par Robert Deutz) était d'être en mesure de spécifier des suffixes pour le rendu. L'idée de départ était de permettre aux extensions de charger un rendu actif spécifique à la version Joomla! ou d'utiliser celle par défaut. Voici un exemple :
$layout = new JLayoutFile('joomla.content.tags', null, array('suffixes' => array('j3x', 'j25')));
echo $layout->render($this->item->tags->itemTags);
Mais ce n'est qu'une des utilisations possibles. Imaginez que vous ayez besoin d'un rendu différent pour les langues RTL (Right to Left - de Droite à Gauche). Vous pouvez l'ajouter à toutes les recherches afin de toujours l'utiliser lorsque le langage RTL est actif. Ou encore, imaginez l'adresse d'un client dont le code postal s'affiche dans différent lieux/formats selon le pays. Vous pouvez ajouter une vérification pour une mise en page spécifique selon le pays du client.
Les rendus secondaires
Un autre des éléments pénibles de JLayouts est que vous ne pouvez pas hériter des paramètres d'un rendu afin de les utiliser pour l'affichage d'une autre petite partie de code. Il faut alors spécifier à nouveau toutes les options. Voyons un autre exemple : la personnalisation des factures. De cette façon, vous pouvez avoir un appel global tel que :
echo JLayoutHelper::render('invoice', $invoiceData);
Et à l'intérieur de ce rendu, quelque chose de ce type :
<div class="invoice">
<div class="customer">
<?php echo $this->sublayout('shopper', $displayData['shopper']); ?>
</div>
<div class="header">
<?php echo $this->sublayout('header', $displayData); ?>
</div>
<div class="products">
<?php echo $this->sublayout('products', $displayData['products']); ?>
</div>
<div class="footer">
<?php echo $this->sublayout('footer', $displayData); ?>
</div>
</div>
Ce qui correspond au rendu de la facture principale appelant des rendus secondaires. Ainsi, les utilisateurs peuvent tout simplement substituer l'en-tête de la facture sans avoir à s'occuper du reste du système.
Lorsque vous appelez un rendu secondaire, le système tente de trouver un dossier portant le même nom que cet affichage et contenant les rendus secondaires. Dans cet exemple, nous aurions alors un rendu principal invoice.php
et dans le même dossier, un sous-dossier nommé invoice
contenant les rendus secondaires (shopper.php
, header.php
, products.php
& footer.php
).
Les rendus secondaires hériteront des paramètres du rendu parent. Ainsi, ils cherchent dans le même include paths, dans le même client, dans le même composant et pour les mêmes suffixes.
Mode de débogage
Lorsque vous commencez à traiter des rendus dans divers include paths, clients, composants... Vous pouvez facilement finir par ne plus savoir d'où le système charge les rendus. C'est pourquoi j'ai inclus un système de débogage UBU (Useful But Ugly - utile mais laid - :D). Pour l'activer, il vous suffit de mettre l'option debug
sur "true" de cette façon :
$layout = new JLayoutFile('joomla.content.tags', null, array('suffixes' => array('j3x', 'j25'), 'debug' => true));
echo $layout->render($this->item->tags->itemTags);
Vous verrez alors quelque chose comme cela :
Où ne pas utiliser les rendus ?
Les rendus sont très sympas lorsque utilisés correctement, mais peuvent vite devenir terribles lorsqu'ils sont utilisés au mauvais endroit. Aujourd'hui, tout le monde veut tout convertir en rendu. C'est pourquoi vous pouvez facilement trouver des rendus qui sont utilisés par des articles, bannières, contacts, clients, liens web, flux RSS. Vous allez me dire "mais c'est cool, non ? On économise du code !". Non ! Nous sommes en train de créer un rendu unique contenant des tonnes de déclarations pour pouvoir faire face à toutes les différences entre les composants.
De mon point de vue, il n'y a aucun intérêt à utiliser un rendu pour la mise en page de quatre malheureux champs. C'est quelque chose qui doit être fait dans le template et qui ne doit jamais être réutilisé en dehors du Core. Alors voilà mon conseil : s'il peut être réutilisé en dehors du core, alors l'utilisation d'un rendu est logique. Exemples de rendus : rendu d'une liste, d'un bouton, d'un menu, d'un champ, de la pagination... Un autre bon conseil : si un élément ne peut être substitué, mieux vaut utiliser un rendu.
Les rendus ne sont pas la solution à tout.
Autres utilisations
Imaginez le JQuery actuel chargé dans le core. Cela s'opère à partir des classes JHtml. Pourquoi ne pas faire une recherche JHtml pour une substitution automatique dans le dossier du composant ? Ainsi, je pourrais avoir ma propre version JQuery personnalisée et testée avec les autres bibliothèques de mon composant. Oui, cela peut entrer en conflit avec les autres exigences d'un module, mais n'est-ce pas ce que nous avions déjà ? Au moins, cela nous éviterait de charger JQuery à plusieurs reprises. D'accord, ce n'est pas vraiment une tâche pour les rendus mais le même concept peut être appliqué au JHtml.
Maintenant, imaginez que le menu haut présente un bug sur un bouton ou dans un élément contenu dans le rendu. Vous pouvez le solutionner par une substitution de rendu dans votre propre composant et attendre jusqu'à ce que le problème soit réglé. C'est également le cas lorsque vous avez une bibliothèque entrant en conflit avec le noyau.
Et ce ne sont que quelques unes des idées du concept.
En conclusion
Les rendus constituent un outil vraiment puissant et sont un des éléments nous permettant d'améliorer les relations entre les développeurs et les designers. Les rendus peuvent être utilisés en de nombreux endroits. Certains n'ont pas encore été découverts et d'autres attendent que quelqu'un fasse le travail. . Voulez-vous nous aider ?