Tagphtml

[Magento 2] Utiliser action method= »setTemplate » pour surcharger un fichier PHTML dans app/code/Vendor/Module plutôt que dans un thème

Je veux surcharger app/code/Magento/LayeredNavigation/view/frontend/templates/layer/view.phtml dans app/code/NakedUi/LayeredNavigation/view/frontend/layer/view.phtml. Source: How to Override a phtml File Using a Custom Module in Magento 2.

Créer un module NakedUi_LayeredNavigation qui contient au minimum les fichiers suivants:

./registration.php

./etc/module.xml

Puis dans ./view/frontend/layout, créer les deux fichiers suivants:

catalog_category_view_type_layered.xml et catalogsearch_result_index.xml

Ne pas oublier de surcharger ./view/frontend/templates/layer/view.phtml

[Magento 2] Comment inclure et utiliser un fichier JS custom placé dans un thème depuis un template PHTML avec data-mage-init

C’est par ici: [Magento 2] Vérifier qu’un utilisateur client est connecté à son compte et afficher son prénom dans un template PHTML.

Voir aussi: [Magento 2] Comment inclure et utiliser un fichier JS custom avec requireJS.

[Magento 2] Appeler un template PHTML depuis une page CMS

Source: How to call a PHTML file within a CMS page Magento 2?

Formule générique:

Bloc par défaut:

[Magento 2] Récupérer dans un template PHTML des informations sur les différentes boutiques de votre site (ID, code, nom, URL, …)

Sources: magento 2 How to get store Id phtml et How to get store information in Magento 2.

Exemple d’informations exploitables dans un fichier PHTML:

[Magento 2] Afficher une liste produits par sous-catégories sur la page principale d’une catégorie

Par défaut, Magento 2 utilise un template PHTML unique pour afficher les listes produits d’une catégorie et de ses sous-catégories. Il s’agit du fichier vendor/magento/module-catalog/view/frontend/templates/product/list.phtml.

L’un des problèmes posé par ce mode de fonctionnement réside dans le fait qu’on se retrouve avec une page catégorie principale/main qui affiche, dans une liste unique, tous les produits contenus dans cette catégorie ainsi que ses sous-catégories et ceux sans aucun distingo. Ce qui nous donne, de manière très schématisée:

Le code décrit dans ce billet va permettre d’obtenir ceci:

Création d’un Helper: app/code/Pdv/Catalog/Helper/Data.php

Note: j’avais déjà créé ce Helper pour récupérer les Simple Products associés à un Configurable Product. Consulter le billet en question pour de plus amples infos si vous ne souhaitez pas exploiter tout le code ci-dessous. Ce Helper étend vendor/magento/module-catalog/Helper/Data.php.

Rajouts par rapport au Helper existant:

Sous la ligne namespace Pdv\Catalog\Helper;:

Sous la ligne protected $typeConfigurableResourceModel; // 1. Du nom du model dont je veux injecter la propriété de la classe:

Dans le constructeur, sous la ligne \Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable $typeConfigurableResourceModel // 2. Demande à Magento une instance de mon configurable ressource model (EN RAJOUTANT UNE VIRGULE en fin de la ligne existante):

Sous la ligne $this->typeConfigurableResourceModel = $typeConfigurableResourceModel; // 3. ...et mappe le paramètre du constructeur avec la propriété de la classe:

Le commentaire:

…est enrichi comme suit:

Et la fonction getCurrentCategory() qui suit…

…est remaniée en:

app/design/frontend/Sodifrance/pdv/Magento_Catalog/templates/product/list_abonnements_category.phtml

Ce template PHTML se contente de boucler, autant de fois qu’il y a de sous-catégories, sur le template Magento_Catalog::product/list_abonnements_subcategory.phtml qui est une version custom du template vendor/magento/module-catalog/view/frontend/templates/product/list.phtml.

L’équivalent de ce fichier list_abonnements_subcategory.phtml DOIT exister dans votre projet. Si vous n’avez pas besoin d’en créer un spécifique, vous pouvez boucler sur le template par défaut fourni par Magento 2. Dans le code ci-dessus: ->setTemplate("Magento_Catalog::product/list.phtml"). Edit: il faut en créer un spécifique pour exploiter notre Helper.

app/design/frontend/Sodifrance/pdv/Magento_Catalog/templates/product/list_abonnements_subcategory.phtml

Ce template PHTML doit partir de vendor/magento/module-catalog/view/frontend/templates/product/list.phtml. Il est impératif de rajouter les lignes suivantes en haut de fichier, sous la ligne $hoverChange = $themeSettingConfig->getStoreConfig('themesettings/catalog/hover_change');:

app/design/frontend/Sodifrance/pdv/Magento_Theme/page_layout/abonnements_category.xml

Reportez-vous à ce billet pour voir comment afficher un layout différent selon une catégorie spécifique. Cette étape est indispensable pour faire pointer notre catégorie vers notre template PHTML spécifique app/design/frontend/Sodifrance/pdv/Magento_Catalog/templates/product/list_abonnements_category.phtml. Un exemple de code pour ce fichier ci-dessous:

Vous voudrez aussi créer le layout XML app/design/frontend/Sodifrance/pdv/Magento_Theme/page_layout/abonnements_subcategory.xml

…pour fairez pointer les sous-catégories vers le template PHTML .

Externaliser le code JS

Afin que le code JS initialement présent au bas du fichier list.phtml ne soit pas exécuté autant de fois qu’il existe de sous-catégories, il a été externalisé dans un fichier app/design/frontend/Sodifrance/pdv/Magento_Catalog/templates/product/list_abonnements_js.phtml et déclaré de la sorte dans nos layouts XML spécifiques:

app/design/frontend/Sodifrance/pdv/Magento_Catalog/templates/product/list_abonnements_js.phtml

Le code de ce fichier, sorti de list.phtml:

[Magento 2] Masquer les décimales pour les prix ronds dans la liste produits

Lorsque mon prix affiche 99,00 €, je souhaite que soit affiché uniquement la valeur avant la virgule: 99 €. Pour celà, il faut surcharger le fichier vendor/magento/module-catalog/view/base/templates/product/price/amount/default.phtml dans un thème.

Remarque: on voit dans notre exemple que le fichier natif est « rangé » dans le dossier base ce qui signifie que cette vue PHTML va servir pour afficher des informations autant en front que dans l’interface d’administration de Magento 2. J’ai cependant besoin de n’afficher mon prix sans décimales qu’en front. Pour ce faire, je vais recréer une version modifiée de mon fichier de départ dans app/design/frontend/Sodifrance/pdv/Magento_Catalog/templates/product/price/amount/default.phtml.

La partie qui nous intéresse plus particulièrement se situe dans l’élément <span class="price-wrapper">:

J’ai remarqué, en parcourant la source de la page avec l’inspecteur d’éléments, qu’il existait dans le bloc <div class="price-box"> un data attribut data-price-amount qui contenait déjà les prix ronds sans décimales (data-price-amount="99" au lieu de data-price-amount="99.00"). L’idée ici est de le ré-exploiter.

Ci-dessus, je créer une variable $dot qui contient juste le caractère .. Je vais avoir besoin de savoir si la valeur de mon data-price-amount contient la valeur de $dot ou pas.

Je crée également une variable $price qui contient la valeur de mon data-price-amount (le prix).

Dans une condition if/else, j’utilise la fonction strpos de PHP pour vérifier si la valeur de $price contient la valeur de $dot.

Si « oui » (!== false), alors je conserve l’affichage standard du prix dans Magento 2 (un <span class="price"></span> avec des décimales, peu importe si le prix est de 99,00 €).

Si « non » (code après le <?php else :?>) j’ajoute un <span class="price-without-decimal"> au-dessus de l’affichage standard du prix dans Magento 2 pour y afficher la valeur de mon attribut data-price-amount (un prix sans décimales, si mon code fonctionne correctement).

Attention: je me retrouve désormais avec 2 prix affichés si je suis dans le cas où la valeur du prix ne contient pas de décimales. J’ai choisi de conserver l’affichage standard du prix dans Magento 2 dans le DOM au cas où il sert (via un javaScript ou autre…) à des calculs.

Pour masquer ce dernier à l’utilisateur, j’utilise CSS:

Le fichier app/design/frontend/Sodifrance/pdv/Magento_Catalog/templates/product/price/amount/default.phtml complet:

(partie en work-in-progress) Si vous voulez pouvoir cibler certaines pages spécifiquement, voici ce qu’il faut mettre dans votre layout XML:

[Magento 2] Créer un Helper pour récupérer sous forme d’objet dans un template PHTML des informations (ID, nom…) sur la catégorie produit en cours

Testé fonctionnel Magento 2.3!

ATTENTION: bien que cette méthode soit fonctionnelle, ce billet consigne mes notes sur la façon de créer un Helper pour récupérer sous forme d’objet dans un template PHTML des informations (ID, nom…) sur catégorie produit en cours. Les fichiers ne sont pas forcément placés aux bons endroits par rapport aux bonnes pratiques Magento 2.

Créer un module

Sodifrance_GetCurrentCategory

app/code/Sodifrance/GetCurrentCategory/etc/di.xml

app/code/Sodifrance/GetCurrentCategory/Model/Layer/Resolver.php

Hérité de vendor/magento/module-catalog/Model/Layer/Resolver.php.

Créer un module

Pdv_Catalog

app/code/Pdv/Catalog/Helper/Data.php

Hérité de vendor/magento/module-catalog/Helper/Data.php.

app/design/frontend/Sodifrance/pdv/Magento_Catalog/templates/product/list_abonnements.phtml

Hérité de vendor/magento/module-catalog/view/frontend/templates/product/list.phtml.

Dans le bloc de code suivant:

…mettre à la suite:

Pour récupérer le nom ou l’ID de la catégorie en cours

La majeure partie des informations récupérables est définie ici: vendor/magento/module-catalog/Model/Category.php. Mais précisément pour le nom et l’ID de la catégorie en cours:

Vous pouvez également utiliser les fonctionnalités d’auto-complétion de votre IDE pour avoir accès à toute la liste des informations contenues dans votre objet PHP $currentCategory en commençant à taper <?php echo $currentCategory->get.

[Magento 2] PHP dans les fichiers PHTML

Les conventions utilisées dans les templates PHP (PHTML) de Magento 2

  • $this no longer applies to the rendering block. Use $block or $block>getData('view_model') to obtain access to the instigating object or its data.
  • Always type hint variables that are automatically imported ($block, $viewModel).
  • Never use squiggly braces: this is a code smell that indicates your block or view model should be doing more work.
  • If you need to use a loop, use the foreach > endforeach constructs (de cette manière: <?php foreach () : ?> puis <?php endforeach ?>).
  • Keep templates to a reasonable minimum. Massive 500 line files are a code smell.
  • Magento now uses <?= instead of <?php echo.
  • Always translate strings in templates that will be displayed to user.
  • Magento templates do not use the if(){ /* … */ } constructs because squiggly braces are harder to discern amongst HTML. A la place, utiliser <?php if (): ?> suivi de <?php else: ?> ou directement de <?php endif; ?>.

Les méthodes communément disponibles pour la variable $block

  • getRootDirectory()
  • getMediaDirectory()
  • getUrl()
  • getBaseUrl()
  • getChildBlock($alias)
  • getChildHtml($alias, $useCache = true)
  • getChildChildHtml($alias, $childChildAlias = '', $useCache = true): this method returns the HTML from a grandchild block.
  • getChildData($alias, $key = ''): calls getData on a child block.
  • formatDate($date = null, $format = \ IntlDateFormatter::SHORT, $showTime = false, $timezone = null)
  • formatTime($time = null, $format = \ IntlDateFormatter::SHORT, $showDate = false)
  • getModuleName()
  • escapeHtml($data, $allowedTags = null)
  • escapeJs($string)
  • escapeHtmlAttr($string, $escapeSingleQuote = true)
  • escapeCss($string)
  • stripTags($data, $allowableTags = null, $allowHtmlEntries = false)
  • escapeUrl($string)
  • getVar($name, $module = null): locates a value from the theme’s etc/view.xml

Comment afficher un child block?

Comment afficher tous les child block?

Afficher un argument défini via un layout XML

Source: Magento 2: Adding Frontend Assets via Layout XML (Alan Storm)

La valeur de test_value sera disponible via $block->getData('test_value') ou $block->getTestValue().

Rendu sécurisé des templates, contenus HTML / JS et Urls

  • HTML: $block->escapeHtml(‘value’, $allowedTags);
  • HTML attributes: $block->escapeHtmlAttr(‘value’, $escapeSingleQuote);
  • JavaScript: $block->escapeJs(‘value’);
  • URLs: $block->escapeUrl($url);

Si la condition d’un booléen est true, afficher quelque chose…

Nous avons créé un attribut produit custom que nous avons nommé best_offer. Il s’agit d’un booléen. Nous allons commencer par stocker sa valeur dans une variable $bestOffer:

Puis, lorsque nous avons besoin d’afficher quelque chose de spécifique si la valeur de la variable $bestOffer est true (attribut configuré à oui en back-office):

Fonction PHP de gestion des variables empty()

Source: Fonctions de gestion des variables: empty().

Nous avons créé un attribut produit custom que nous avons nommé offer_content. Il s’agit d’un champ texte. Nous allons commencer par stocker sa valeur dans une variable $offerContent:

Puis, si la variable ne vaut pas 0, n’est pas vide, est définie, afficher sa valeur:

Utitiser la fonction PHP strst() pour supprimer une partie d’une chaîne de caractères jusqu’à un caractère spécifié

Ici, pour la chaîne de caractère toto-titi, je veux conserver -titi uniquement:

Utitiser la fonction PHP str_replace() pour supprimer un caractère spécifié

Ici, pour la chaîne de caractère -titi, je veux retirer le caractère - pour conserver titi uniquement:

[Magento 2] Exploiter le widget javascript jQuery natif Modal dans un fichier PHTML en notation déclarative

Voir aussi: [Magento 2] Exploiter le widget javascript jQuery natif Accordion dans le fichier PHTML des filtres produit (page category).

Source: Magento 2.3 DevDocs (officiel) – Modal widget sample code.

L’exemple suivant montre comment, en notation déclarative (bonne pratique dans Magento 2), initialiser le widget Modal et passer des options pendant l’initialisation. Il montre également comment ouvrir la modale en cliquant sur un bouton.

[Magento 2] Exploiter le widget javascript jQuery natif Accordion dans le fichier PHTML des filtres produit (page category)

Note: ce widget Accordion fait partie d’une collection étendue de widgets fournis de base par Magento 2 (à ne pas confondre avec la bibliothèque UI Magento 2, fournie de base également, et qu’il convient de connaître aussi.

Pour ce tuto, nous allons afficher les différentes familles de tri produits (catégorie, taille, activity, color, erin recommends, genre, material, nouveau, prix, etc…) sous forme d’accordéons. De base, ils s’affichent tous ouverts, y-compris en vue Mobile ce qui force l’utilisateur à scroller bas dans la page avant de voir apparaître le premier produit. Le fonctionnalités voulues pour ce accordéon:

  • tous les accordéons (différentes familles de tri) sont ouverts au chargement de la page
  • plusieurs accordéons peuvent rester ouverts simultanément

(Note pour plus tard: il peut être intéressant, dans le cadre de la découverte des media-queries côté JS, d’initialiser ce widget avec des options différentes en fonction de l’affichage mobile/desktop).

A noter: il existe plusieurs méthodes pour initialiser du code javascript dans une vue dans Magento 2. Nous allons nous concentrer sur deux d’entre-elles qui ne sont ni meilleures, ni moins bonnes que les autres.

Imperative notation

En initialisant notre widget directement dans un fichier *.phtml, entre balises <script type="text/javascript">.

Commencer par éditer le fichier *.phtml app\design\frontend\<Vendor_name>\<theme_name>\Magento_LayeredNavigation\templates\layer\view.phtml qui constitue la base de la vue des différents filtres. Notez bien l’ajout, par rapport à la vue que nous surchargeons, des attributs data-role="collapsible", data-role="trigger" et data-role="content" respectivement placés sur les éléments dt, a et dd, ainsi que de la classe filter-options-collapsible-trigger placée sur le nouvellement ajouté élément a.

Le widget s’initialise ensuite comme suit avec requireJS (code placé dans le même fichier view.phtml, immédiatement après la ligne <?php if ($block->canShowBlock()): ?>):

Declarative notation

Le widget va s’initialiser sans avoir recours à un require déclaré dans une balise <script />, par de biais d’un attribut data-mage-init placé directement sur l’élément à partir duquel nous venons précédemment d’initialiser notre widget à la manière de jQuery.

Dans les deux cas on n’oublie pas de lancer un cache:clean en console!

© 2020 devfrontend.info

Theme by Anders NorénUp ↑