Accéder au contenu principal

Ne plus étendre dans Magento 2

 

Une habitude coûteuse

Depuis des années, nous avons pris l'habitude d'étendre un peu tout dans Magento (1 surtout mais 2 également) : Contrôleurs, Blocs... L'introduction de l'injection de dépendances à changé la donne et nous allons faire le tour des principales alternatives qui se présentent à nous. Mais en premier lieu, pourquoi le faire.

L'extension veut dire qu'il faut vérifier la compatibilité de la classe fille avec la classe mère. Cela freine les plus courageux quand il est question de faire un changement de version et entraîne des coûts plus ou moins élevés pour l'évolution du projet vers une version plus récente de Magento ou l'installation d'un nouveau module.

L'extension entend également de faire suivre l'ensemble de la logique de la classe parente dont nous n'avons pas forcément besoin. 

Les outils à notre disposition

Les modèles de vue (ViewModels)

Les modèles de vue permettent non seulement de ne pas avoir à assurer la rétrocompatibilité du code mais également d'avoir des modèles qui ont une certaine logique pour un élément donné et qui peuvent être injectés dans différents blocs. Cela respecte le principe de responsabilité unique (SRP aka Single Responsibility Principle) et permet une maintenance aisée.

On trouve souvent des Helpers pour effectuer ces tâches mais ce n'est pas leur rôle et dans beaucoup de cas, ces classes fourre-tout ont tendance à grossir plus que nécessaire avec les impacts sur les performances qui en découlent. L'avantage du modèle de vue est qu'il ne sera utilisé que pour la vue même dans un projet où plusieurs développeurs vont mettre leur touche personnelle. De plus, il n'a pas besoin d'être appelé dans les templates comme c'est le cas des helpers. L'injection se fait automatiquement grâce à une simple déclaration dans le xml.

Pour la pratique, je vous invite à regarder la documentation officielle et le blog de Yreo.

Injection

L'extension d'une classe est souvent le résultat d'une réflexion qui emmène à penser que si ça a été fait, ce n'est plus à faire. Mais ce n'est pas toujours le cas. J'ai récemment du changer toute la logique de la mise au panier pour un besoin spécifique. Il n'y a pas si longtemps, j'aurais sans doute étendu \Magento\Checkout\Controller\Cart\Add en modifiant les méthodes idoines. Seulement, j'aurais embarqué beaucoup de logique de l'action parente dont je n'aurai jamais eu besoin puisque mon but était de modifier la logique de base justement.

Qui plus est, les actions ou les modèles dans Magento 2 comptent souvent (toujours) des méthodes privées qu'il faut copier dans la classe fille pour avoir quelque chose qui fonctionne.

Créer la classe sans surcharger permet de n'embarquer que ce dont on a besoin, s'affranchir des éventuelles mises à jour de la classe mère et ne pas avoir du code inutile à droite et à gauche. Je ferai un article sur les différentes manières d'injecter dans Magento 2 en fonction du besoin mais on trouve un bel aperçu dans la documentation officielle.

Interception

Si pour une raison précise, il est nécessaire de changer l'entrée ou la sortie d'une méthode, il n'est pas nécessaire d'avoir recours à l'extension de la classe mère pour ne surcharger que la méthode en question. Pour cela, il existe les intercepteurs (ou plugins).

Ils sont au nombre de trois :

  • Avant la méthode (before)
  • Après la méthode (after)
  • Autour de la méthode (around)

Si les intercepteurs avant et après sont peu gourmands en ressource, celui qui entoure la méthode est à utiliser avec parcimonie. Il est possible d'injecter des éléments qui ne sont pas présents dans la méthode interceptée via le constructeur de l'intercepteur. Les gains en terme de compatibilité et de maintenabilité sont énormes.

Conclusion

S'il vous semble nécessaire d'étendre un bloc, il est peu probable que le modèle de vue ne puisse pas faire ce dont vous avez besoin.

Si vous avez besoin de modifier une petite partie de la logique d'une classe, pensez aux intercepteurs.

S'il vous faut modifier une grosse partie de la logique, il est sans doute plus judicieux de partir de 0 pour injecter ce dont vous avez besoin.

Sinon, pensez à utiliser les préférences.

Commentaires

Posts les plus consultés de ce blog

[PHP] Faire un petit MVC avec des routes

Pour bon nombre de petits projets, il n'est pas nécessaire de taper dans les frameworks MVC comme Zend ou Symphony qui sont très lourds et un petit truc maison doit suffire. Je vais essayer de donner quelques tuyaux pour pouvoir faire son MVC maison avec des routes qui dirigent vers les contrôleurs et les actions. Tout d'abord, il faut créer un fichier index.php à la racine de votre site qui va contenir le lien vers tout ce dont vous avez besoin pour faire vos routes. Ensuite, vous devez créer un dossier controlleur (si vous voulez reproduire la faute de frappe de l'exemple) dans lequel vous aurez tous vos contrôleurs. Vous pouvez éventuellement diviser ce dossier en plusieurs dossiers distincts qui contiendront les différentes parties de votre site. Veillez à appeler vos classes en rapport avec vos règles de is_callable. Dans mon exemple, le chemin vers le dossier est en minuscule et la première lettre du fichier est en majuscule. Par exemple : la classe /controlleur/fron

Injecter des icônes font-awesome via JavaScript

Les icônes de font-awesome sont traduites en SVG ( Scalable Vector Graphics) à la volée grâce à un script. Le problème quand on injecte du HTML dans le DOM est que le script ne s'exécute pas correctement et l'icône n’apparaît pas. Pour palier à cela, il est possible d'utiliser un générateur de ressources qui est embarqué dans la librairie font-awesome. Pour éviter au script de s'exécuter sur des icônes qui se répètent, la librairie comprend un script qui permet de traduire une seule fois l'image en SVG pour être réutiliser dans des listes. Comme disent les anglo-saxons, et voilà ! Il y a d'autres exemples d'utilisation :  https://fontawesome.com/how-to-use/on-the-web/advanced/svg-symbols    

Modifier le type d'entrée d'un attribut produit dans Magento

Aujourd'hui, suite à une modification différente via l'administration dans deux instances du même site (dev et staging), j'ai du modifié le type d'un attribut de liste déroulante vers multi-select. Pour y parvenir, j'ai du faire quelques modifications dans la base de données directement puisqu'il n'est pas possible de le faire via l'administration. On voit que le type d'entrée est grisé Pour faire cette modification, je me suis basé sur un gist que j'ai adapté selon mes besoins : Et voilà !