Comment ajouter un champ personnalisé pour les valeurs d'option dans les options de produit avancées
Publié: 2020-11-20Dans l'article précédent, vous avez appris à créer des champs d'options personnalisés Magento. Nous avons également découvert comment afficher les données de champ à la fois sur le front-end de la page produit et sur la page de commande dans le panneau d'administration.
Qu'y a-t-il maintenant ?
Apprenons à ajouter le même champ GTIN personnalisé pour les valeurs d'option et à l'afficher sur le front-end de la page du produit.
Table des matières
- Étape 1. Création de nouveaux modules
- 1. composer.json
- 2. etc/module.xml
- 3. inscription.php
- Étape 2. Ajout d'un nouveau champ à la base de données
- Étape 3. Ajouter une logique pour travailler avec le backend
- Étape 4. Ajout d'un paramètre pour désactiver l'affichage du champ GTIN pour la configuration avancée des options de produit
- Étape #5. Affichage d'un nouveau champ sur le front-end de la page produit
Étape 1. Création de nouveaux modules
Commençons par la création du nouveau module, dont le processus a été couvert en détail dans cet article de blog Mageworx.
Ainsi, sans plus tarder, voici le code dont nous aurons besoin :
1. composer.json
{ "name": "mageworx/module-optionvaluegtin", "description": "N/A", "require": { "magento/framework" : ">=100.1.0 <101", "magento/module-catalog": ">=101.0.0 <104" }, "type": "magento2-module", "version": "1.0.0", "license": [ "OSL-3.0", "AFL-3.0" ], "autoload": { "files": [ "registration.php" ], "psr-4": { "VendorName\\OptionValueGtin\\": "" } } }
2. etc/module.xml
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> <module name="VendorName_OptionValueGtin" setup_version="1.0.0"> <sequence> <module name="Magento_Catalog"/> <module name="MageWorx_OptionBase"/> </sequence> </module> </config>
3. inscription.php
<?php \Magento\Framework\Component\ComponentRegistrar::register( \Magento\Framework\Component\ComponentRegistrar::MODULE, 'VendorName_OptionValueGtin', __DIR__ );
Étape 2. Ajout d'un nouveau champ à la base de données
Il est temps de créer le champ GTIN et de l'ajouter à la table correspondante dans la base de données.
Comme nous ajoutons un champ pour les valeurs d'option, la table `catalog_product_option_type_value` sera requise.
Créons le fichier suivant :
`app/code/VendorName/OptionValueGtin/Setup/InstallSchema.php`
<?php namespace VendorName\OptionValueGtin\Setup; use Magento\Framework\Setup\InstallSchemaInterface; use Magento\Framework\Setup\ModuleContextInterface; use Magento\Framework\Setup\SchemaSetupInterface; use Magento\Framework\DB\Ddl\Table; class InstallSchema implements InstallSchemaInterface { public function install(SchemaSetupInterface $setup, ModuleContextInterface $context) { $setup->startSetup(); $setup->getConnection()->addColumn( $setup->getTable('catalog_product_option_type_value'), 'gtin', [ 'type' => Table::TYPE_TEXT, 'nullable' => true, 'default' => null, 'comment' => 'Gtin (added by MageWorx Option Value Gtin)', ] ); $setup->endSetup(); } }
Étape 3. Ajouter une logique pour travailler avec le backend
Utilisez le mécanisme de modification de pool pour que Magento ajoute un champ à l'option personnalisée.
Créons le fichier suivant :
`app/code/VendorName/OptionValueGtin/etc/adminhtml/di.xml`
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <virtualType name="MageWorx\OptionBase\Ui\DataProvider\Product\Form\Modifier\Pool"> <arguments> <argument name="modifiers" xsi:type="array"> <item name="mageworx-option-value-gtin" xsi:type="array"> <item name="class" xsi:type="string">MageWorx\OptionValueGtin\Ui\DataProvider\Product\Form\Modifier\OptionValueGtin</item> <item name="sortOrder" xsi:type="number">72</item> </item> </argument> </arguments> </virtualType> </config>
Ici:
Nous ajoutons notre modificateur au pool général de l'extension Advanced Product Options pour Magento 2―
`MageWorx\OptionBase\Ui\DataProvider\Product\Form\Modifier\Pool`.
`VendorName\OptionValueGtin\Ui\DataProvider\Product\Form\Modifier\OptionValueGtin` est la classe du modificateur.
Dessous:
Voir le code qui permet d'ajouter notre champ au formulaire `app/code/VendorName/OptionValueGtin/Ui/DataProvider/Product/Form/Modifier/OptionValueGtin.php` :
<?php namespace VendorName\OptionValueGtin\Ui\DataProvider\Product\Form\Modifier; use Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\AbstractModifier; use Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\CustomOptions; use Magento\Ui\Component\Form\Element\Input; use Magento\Ui\Component\Form\Element\DataType\Number; use Magento\Ui\Component\Form\Field; use MageWorx\OptionBase\Ui\DataProvider\Product\Form\Modifier\ModifierInterface; class OptionValueGtin extends AbstractModifier implements ModifierInterface { /** * @var array */ protected $meta = []; /** * {@inheritdoc} */ public function modifyData(array $data) { return $data; } /** * {@inheritdoc} */ public function modifyMeta(array $meta) { $this->meta = $meta; $this->addFields(); return $this->meta; } /** * Adds fields to the meta-data */ protected function addFields() { $groupCustomOptionsName = CustomOptions::GROUP_CUSTOM_OPTIONS_NAME; $optionContainerName = CustomOptions::CONTAINER_OPTION; // Add fields to the values $valueFeaturesFields = $this->getValueFieldsConfig(); $this->meta[$groupCustomOptionsName]['children']['options']['children']['record']['children'] [$optionContainerName]['children']['values']['children']['record']['children'] = array_replace_recursive( $this->meta[$groupCustomOptionsName]['children']['options']['children']['record']['children'] [$optionContainerName]['children']['values']['children']['record']['children'], $valueFeaturesFields ); } /** * The custom option fields config * * @return array */ protected function getValueFieldsConfig() { $fields['gtin'] = $this->getGtinFieldConfig(); return $fields; } /** * Get gtin field config * * @return array */ protected function getGtinFieldConfig() { return [ 'arguments' => [ 'data' => [ 'config' => [ 'label' => __('GTIN'), 'componentType' => Field::NAME, 'formElement' => Input::NAME, 'dataType' => Number::NAME, 'dataScope' => 'gtin', 'sortOrder' => 92 ], ], ], ]; } /** * Check is current modifier for the product only * * @return bool */ public function isProductScopeOnly() { return false; } /** * Get sort order of modifier to load modifiers in the right order * * @return int */ public function getSortOrder() { return 32; } }
Maintenant, installez l'extension et vérifiez que tout est fait correctement, c'est-à-dire,
- module php bin/magento : activer VendorName_OptionValueGtin
- configuration de php bin/magento : mise à niveau
- php bin/cache magento : vider
Comme vous pouvez le voir, le champ nouvellement ajouté s'affiche maintenant :
Étape 4. Ajout d'un paramètre pour désactiver l'affichage du champ GTIN pour la configuration avancée des options de produit
Et si on mélangeait un peu notre article ?
Je propose d'ajouter de nouvelles fonctionnalités - la possibilité d'activer / désactiver l'affichage du champ GTIN pour les valeurs d'option sur le front-end de la page du produit.
Vous devrez créer le fichier :
`app/code/VendorName/OptionValueGtin/etc/adminhtml/system.xml`
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd"> <system> <tab sortOrder="2001"> <label>MageWorx</label> </tab> <section translate="label" type="text" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1"> <label><![CDATA[Advanced Product Options]]></label> <tab>mageworx</tab> <resource>VendorName_OptionValueGtin::config_optionvaluegtin</resource> <group translate="label" type="text" sortOrder="100" showInDefault="1" showInWebsite="1" showInStore="1"> <label><![CDATA[Option Value GTIN]]></label> <field translate="label" type="select" sortOrder="80" showInDefault="1" showInWebsite="1" showInStore="1"> <label><![CDATA[Enable Option's Value 'GTIN']]></label> <source_model>Magento\Config\Model\Config\Source\Yesno</source_model> </field> </group> </section> </system> </config>
Pour la simplicité:
Nous allons ajouter le nouvel onglet Option Value GTIN à la configuration de notre extension Advanced Product Options. Vous devriez également pouvoir créer un onglet dans votre module.
La nouvelle classe d'assistance doit être créée. Là, nous obtiendrons des données sur le réglage.
Alors, créons et remplissons la classe suivante :
`app/code/VendorName/OptionValueGtin/Helper/Data.php`
<?php namespace VendorName\OptionValueGtin\Helper; use Magento\Framework\App\Helper\AbstractHelper; use Magento\Store\Model\ScopeInterface; use Magento\Framework\App\Helper\Context; class Data extends AbstractHelper { const XML_PATH_DEFAULT_OPTION_VALUE_GTIN = 'mageworx_apo/optionvaluegtin/use_optionvaluegtin'; /** * Additional product attributes for product_attributes table * * @var array */ protected $additionalProductAttributes; /** * @param Context $context */ public function __construct( Context $context ) { parent::__construct($context); } /** * Check if option value GTIN enabled * * @param int|null $storeId * @return string */ public function isOptionValueGtinEnabled($storeId = null) { return $this->scopeConfig->getValue( self::XML_PATH_DEFAULT_OPTION_VALUE_GTIN, ScopeInterface::SCOPE_STORE, $storeId ); } }
N'oubliez pas d'enregistrer les modifications et de vider le cache.
Le paramètre devrait s'afficher dans le panneau d'administration.
Étape #5. Affichage d'un nouveau champ sur le front-end de la page produit
Vous vous souvenez de ce dont nous avons parlé dans l'article précédent ?
Nous avons mentionné que notre module MageWorx_OptionBase possède déjà la méthode `getExtendedOptionsConfig()` qui collecte et affiche tous nos attributs personnalisés sur le front-end via des blocs.
Pour voir comment il est implémenté, ouvrez la classe suivante :
`app/code/MageWorx/OptionBase/Block/Product/View/Options.php`
À présent:
Créez un modèle avec notre attribut :
`app/code/VendorName/OptionValueGtin/Model/Attribute/OptionValue/Gtin.php`
<?php namespace VendorName\OptionValueGtin\Model\Attribute\OptionValue; use MageWorx\OptionBase\Model\Product\Option\AbstractAttribute; class Gtin extends AbstractAttribute { /** * @return string */ public function getName() { return 'gtin'; } }
Via l'injection de dépendances , ajoutez l'attribut au bloc d'attributs généraux de l'extension Advanced Product Options et créez le fichier suivant :
`app/code/VendorName/OptionValueGtin/etc/di.xml`
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <!-- Data --> <type name="MageWorx\OptionBase\Model\Product\Option\Value\Attributes"> <arguments> <argument name="data" xsi:type="array"> <item name="gtin" xsi:type="object">VendorName\OptionValueGtin\Model\Attribute\OptionValue\Gtin</item> </argument> </arguments> </type> </config>
À présent:
Créez notre nouveau bloc et un modèle pour celui-ci :
`app/code/VendorName/OptionValueGtin/Block/ValueGtin.php`
<?php namespace MageWorx\OptionValueGtin\Block; use Magento\Framework\Json\EncoderInterface; use Magento\Framework\View\Element\Template; use Magento\Framework\View\Element\Template\Context; use MageWorx\OptionValueGtin\Helper\Data as Helper; class ValueGtin extends Template { /** * @var EncoderInterface */ protected $jsonEncoder; /** * @var Helper */ protected $helper; /** * @param Context $context * @param EncoderInterface $jsonEncoder * @param Helper $helper * @param array $data */ public function __construct( Context $context, EncoderInterface $jsonEncoder, Helper $helper, array $data = [] ) { parent::__construct( $context, $data ); $this->jsonEncoder = $jsonEncoder; $this->helper = $helper; } /** * @return string */ public function getJsonData() { $data = [ 'isOptionValueGtinEnabled' => $this->helper->isOptionValueGtinEnabled($this->_storeManager->getStore()) ]; return $this->jsonEncoder->encode($data); } }
Ici, nous avons obtenu des données sur le paramètre de la classe d'assistance.
Prochain:
En utilisant la méthode `getJsonData()`, rendons les données sur le front-end en utilisant le modèle que nous sommes sur le point de créer :
`app/code/VendorName/OptionValueGtin/view/frontend/templates/config.phtml`
<?php /** @var \VendorName\OptionValueGtin\Block\ValueGtin $block */ ?> <script> require([ 'jquery', 'optionValueGtin', 'uiRegistry' ], function ($, optionValueGtin, registry) { var optionBase = registry.get('mageworxOptionBase'); if (optionBase) { optionBase.addUpdater(7, optionValueGtin(<?= /* @noEscape */ $block->getJsonData() ?>)); } else { var updaters = registry.get('mageworxOptionUpdaters'); if (!updaters) { updaters = {}; } updaters[7] = optionValueGtin(<?= /* @noEscape */ $block->getJsonData() ?>); registry.set('mageworxOptionUpdaters', updaters); } }); </script>
Nous avons utilisé le mécanisme de mixins JavaScript pour afficher les valeurs du champ GTIN .
Et après?
Prenons une approche différente et créons un widget js, qui sera utilisé pour afficher les nouvelles données sur la page produit.
Définissez le nouveau js :
`app/code/VendorName/OptionValueGtin/view/frontend/requirejs-config.js`
var config = { map: { '*': { optionValueGtin: 'VendorName_OptionValueGtin/js/option-value-gtin' } } };
Il est grand temps de créer le widget lui-même. Il contiendra toute la logique du travail avec le nouvel attribut sur le front-end.
Dans le fichier d'exemple, implémentons la logique d'affichage du GTIN pour les options de sélection, et pour les options de radio et de case à cocher séparément.
Ce seront deux logiques différentes car la logique dans le travail et le balisage de ces options diffèrent l'une de l'autre :
`app/code/VendorName/OptionValueGtin/view/frontend/web/js/option-value-gtin.js`
define([ 'jquery', 'Magento_Catalog/js/price-utils', 'underscore', 'jquery/ui' ], function ($, utils, _) { 'use strict'; $.widget('mageworx.optionValueGtin', { options: { optionConfig: {} }, /** * * @param optionConfig * @param productConfig * @param base * @param self */ firstRun: function firstRun(optionConfig, productConfig, base, self) { if (parseFloat(this.options.isOptionValueGtinEnabled)) { var extendedOptionsConfig = typeof base.options.extendedOptionsConfig != 'undefined' ? base.options.extendedOptionsConfig : {}; for (var option_id in optionConfig) { if (!optionConfig.hasOwnProperty(option_id)) { continue; } var $option = base.getOptionHtmlById(option_id); this._addValueGtin($option, optionConfig, extendedOptionsConfig); } } }, /** * Add description to the values * @param $option * @param optionConfig * @param extendedOptionsConfig * @private */ _addValueGtin: function _addValueGtin($option, optionConfig, extendedOptionsConfig) { var self = this, $options = $option.find('.product-custom-option'); //selectable options $options.filter('select').each(function (index, element) { var $element = $(element), optionId = utils.findOptionId($element), value = extendedOptionsConfig[optionId]['values']; if ($element.attr('multiple') && !$element.hasClass('mageworx-swatch')) { return; } if (typeof value == 'undefined' || _.isEmpty(value)) { return; } var gtinTitle = 'GTIN: '; var $gtin = $('<div class="option-value-gtin"></div>', { style: 'display: none' }); var $label = $option.find('.control'); $element.parent().prepend($gtin); $element.on('change', function (e) { var valueId = $element.val(); if (!_.isUndefined(value[valueId]) && !_.isEmpty(value[valueId]['gtin']) ) { if ($label.length > 0) { $label .first() .after($gtin.text(gtinTitle + value[valueId]['gtin'])); } $gtin.show(); } else { $gtin.hide(); } }); if ($element.val()) { $element.trigger('change'); } }); $options.filter('input[type="radio"], input[type="checkbox"]').each(function (index, element) { var $element = $(element), optionId = utils.findOptionId($element), value = extendedOptionsConfig[optionId]['values']; if ($element.attr('multiple') && !$element.hasClass('mageworx-swatch')) { return; } if (typeof value == 'undefined' || _.isEmpty(value)) { return; } var gtinTitle = 'GTIN: '; var $gtin = $('<div class="option-value-gtin-redio-check"></div>'); var $label = $option.find('.control'); $element.parent().append($gtin); var valueId = $element.val(); if (!_.isUndefined(value[valueId]) && !_.isEmpty(value[valueId]['gtin'])) { $gtin.text(gtinTitle + value[valueId]['gtin']); } if ($element.val()) { $element.trigger('change'); } }); }, }); return $.mageworx.optionValueGtin; });
Que diriez-vous d'ajouter des styles?
`app/code/VendorName/OptionValueGtin/view/frontend/web/css/valueGtin.css`
.option-value-gtin, .option-value-gtin-redio-check { color: #1da0e0; font-weight: 700; margin-top: 5px; } .option-value-gtin-redio-check { display: contents; }
Il ne reste plus qu'à connecter notre bloc et les styles.
Pour cela, créez le fichier suivant :
`app/code/VendorName/OptionValueGtin/view/frontend/layout/catalog_product_view.xml`
<?xml version="1.0"?> <page layout="1column" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <head> <css src="VendorName_OptionValueGtin::css/valueGtin.css"/> </head> <body> <referenceBlock name="product.info.options.wrapper"> <container name="vendorname.option.value.gtin.container" after="product.info.options"> <block class="VendorName\OptionValueGtin\Block\ValueGtin" name="vendorname.option.value.gtin" template="VendorName_OptionValueGtin::config.phtml"/> </container> </referenceBlock> </body> </page>
Nous avons presque fini.
Avant d'exécuter la vérification finale, n'oubliez pas de vider le cache et de déployer à nouveau le contenu statique :
- php bin/cache magento : vider
- php bin/magento static-content:déployer
Et enfin:
Connectez-vous au panneau d'administration.
Créez un produit avec des options personnalisées dans le produit Magento.
Dans notre exemple, j'ai ajouté une liste déroulante, une nuance, une radio et une case à cocher.
N'oubliez pas de remplir nos nouveaux champs GTIN pour les valeurs d'option correspondantes.
Enregistrez le produit.
Il est temps de voir à quoi tout cela ressemble sur le front-end :
Que pensez-vous du résultat ?
Veuillez partager vos commentaires sur l'article dans le champ des commentaires ci-dessous. A-t-il été facile pour Magento d'ajouter un champ aux options personnalisées ?