Comment ajouter un champ aux options personnalisées dans Magento 2 ?
Publié: 2019-07-16Vous savez tous à quel point il est pratique d'utiliser les options personnalisables des produits. Nous avons une puissante suite d'options de produits avancées qui étend considérablement la fonctionnalité standard des options personnalisables. Les champs personnalisés sont à la base de certaines fonctionnalités de l'extension. Ces champs sont ajoutés à des types d'options spécifiques, comme une case à cocher ou une zone de texte.
Dans l'article, je ferai de mon mieux pour expliquer comment vous pouvez ajouter rapidement et facilement les champs nécessaires à la base de données et au panneau d'administration. Ayons un aperçu.
1. Créer un nouveau module
Commençons par créer un module MageWorx_Option. Nous allons tout faire en utilisant ce module comme exemple.
Créons le répertoire suivant : app/code/MageWorx/Option. Pour enregistrer un module, nous aurons besoin de quelques fichiers standards :
<?php \Magento\Framework\Component\ComponentRegistrar::register( \Magento\Framework\Component\ComponentRegistrar::MODULE, 'MageWorx_Option', __DIR__ ); composer.json: { "name": "mageworx/module-option", "description": "N/A", "require": { "magento/module-catalog" : ">=101.0.0 <104", "magento/module-ui" : ">=100.1.0 <102" }, "type": "magento2-module", "version": "1.0.0", "license": [ "OSL-3.0", "AFL-3.0" ], "autoload": { "files": [ "registration.php" ], "psr-4": { "MageWorx\\Option\\": "" } } } 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="MageWorx_Option" setup_version="1.0.0"> <sequence> <module name="Magento_Catalog"/> <module name="Magento_Ui"/> </sequence> </module> </config>
2. Ajouter nos nouveaux champs à la base de données
Par exemple, nous souhaitons mettre en évidence l'une des options du front-end d'une manière ou d'une autre. Ajoutons un champ de case à cocher pour une option "Est une offre spéciale" et un champ de texte "Description" pour les valeurs d'options sélectionnables (liste déroulante, case à cocher, bouton radio, multi-sélection).
Tout d'abord, nous devrons l'ajouter à la base de données dans les tables correspondantes. Pour cela, ajoutez le fichier suivant : app/code/MageWorx/Option/Setup/InstallSchema.php.
<?php namespace MageWorx\Option\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'), 'is_special_offer', [ 'type' => Table::TYPE_BOOLEAN, 'unsigned' => true, 'nullable' => false, 'default' => '0', 'comment' => 'Special Offer Flag', ] ); $setup->getConnection()->addColumn( $setup->getTable('catalog_product_option_type_value'), 'description', [ 'type' => Table::TYPE_TEXT, 'nullable' => true, 'default' => null, 'comment' => 'Description', ] ); $setup->endSetup(); } }
Le champ "Est une offre spéciale" sera désactivé par défaut.
Ensuite, nous pouvons installer le module.
Pour ce faire, exécutez les commandes suivantes dans la console :
sudo -u www-data php bin/magento module:enable MageWorx_Option sudo -u www-data php bin/magento setup:upgrade
3. Ajoutez une logique pour travailler avec le backend
À ce stade, ajoutons le mécanisme de pool-modifiers à notre module, que Magento 2 utilise pour combiner toutes les fonctionnalités nécessaires sur une page produit dans le panneau d'administration.
Pour cela, ajoutons le fichier suivant :
app/code/MageWorx/Option/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="Magento\CatalogStaging\Ui\DataProvider\Product\Form\Modifier\Pool" type="Magento\Ui\DataProvider\Modifier\Pool"> <arguments> <argument name="modifiers" xsi:type="array"> <item name="mageworx-option-all" xsi:type="array"> <item name="class" xsi:type="string">MageWorx\Option\Ui\DataProvider\Product\Form\Modifier\All</item> <item name="sortOrder" xsi:type="number">71</item> </item> </argument> </arguments> </virtualType> <virtualType name="Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\Pool" type="Magento\Ui\DataProvider\Modifier\Pool"> <arguments> <argument name="modifiers" xsi:type="array"> <item name="mageworx-option-all" xsi:type="array"> <item name="class" xsi:type="string">MageWorx\Option\Ui\DataProvider\Product\Form\Modifier\All</item> <item name="sortOrder" xsi:type="number">71</item> </item> </argument> </arguments> </virtualType> <virtualType name="MageWorx\Option\Ui\DataProvider\Product\Form\Modifier\Pool" type="Magento\Ui\DataProvider\Modifier\Pool"> <arguments> <argument name="modifiers" xsi:type="array"> </argument> </arguments> </virtualType> <type name="MageWorx\Option\Ui\DataProvider\Product\Form\Modifier\All"> <arguments> <argument name="pool" xsi:type="object">MageWorx\Option\Ui\DataProvider\Product\Form\Modifier\Pool</argument> </arguments> </type> <virtualType name="MageWorx\Option\Ui\DataProvider\Product\Form\Modifier\Pool"> <arguments> <argument name="modifiers" xsi:type="array"> <item name="mageworx-option-base" xsi:type="array"> <item name="class" xsi:type="string">MageWorx\Option\Ui\DataProvider\Product\Form\Modifier\Base</item> <item name="sortOrder" xsi:type="number">72</item> </item> </argument> </arguments> </virtualType> </config>
Il est maintenant temps de créer notre classe MageWorx\Option\Ui\DataProvider\Product\Form\Modifier\All, qui n'ajoute rien de nouveau en soi au formulaire Options personnalisables sur la page du produit. En utilisant l' injection de dépendance (DI), il ajoutera les champs nécessaires sur la page du produit.
En fait, notre suite d'options de produit avancées ajoute environ 40 champs et autres structures complexes, qui sont ajoutés à l'aide de plus de 10 packages inclus dans l'extension. Comme nous n'avons pas besoin d'une structure aussi complexe ici, nous n'utiliserons qu'un seul modificateur de classe ―
MageWorx\Option\Ui\DataProvider\Product\Form\Modifier\Base.
Vous vous demandez peut-être pourquoi nous spécifions le sort_order = 71 suivant. Tout cela peut s'expliquer par la fonctionnalité standard de Magento 2, où les champs pour les options personnalisables sont ajoutés sous sort_order = 70.
Ci-dessous, jetez un œil à la classe MageWorx\Option\Ui\DataProvider\Product\Form\Modifier\All, qui est présentée par un itérateur régulier :
app/code/MageWorx/Option/Ui/DataProvider/Product/Form/Modifier/All.php
<?php namespace MageWorx\Option\Ui\DataProvider\Product\Form\Modifier; use Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\AbstractModifier; use Magento\Ui\DataProvider\Modifier\PoolInterface; class All extends AbstractModifier implements \Magento\Ui\DataProvider\Modifier\ModifierInterface { /** * @var PoolInterface */ protected $pool; /** * @var array */ protected $meta = []; /** * @param PoolInterface $pool */ public function __construct( PoolInterface $pool ) { $this->pool = $pool; } /** * {@inheritdoc} */ public function modifyData(array $data) { /** @var \Magento\Ui\DataProvider\Modifier\ModifierInterface $modifier */ foreach ($this->pool->getModifiersInstances() as $modifier) { $data = $modifier->modifyData($data); } return $data; } /** * {@inheritdoc} */ public function modifyMeta(array $meta) { $this->meta = $meta; /** @var \Magento\Ui\DataProvider\Modifier\ModifierInterface $modifier */ foreach ($this->pool->getModifiersInstances() as $modifier) { $this->meta = $modifier->modifyMeta($this->meta); } return $this->meta; } }
Fondamentalement, il est maintenant temps de créer un fichier, qui ajoutera nos champs au formulaire Options personnalisables :
app/code/MageWorx/Option/Ui/DataProvider/Product/Form/Modifier/Base.php
<?php namespace MageWorx\Option\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\Checkbox; use Magento\Ui\Component\Form\Element\DataType\Text; use Magento\Ui\Component\Form\Field; class Base extends AbstractModifier { /** * @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; $commonOptionContainerName = CustomOptions::CONTAINER_COMMON_NAME; // Add fields to the option $this->meta[$groupCustomOptionsName]['children']['options']['children']['record']['children'] [$optionContainerName]['children'][$commonOptionContainerName]['children'] = array_replace_recursive( $this->meta[$groupCustomOptionsName]['children']['options']['children']['record']['children'] [$optionContainerName]['children'][$commonOptionContainerName]['children'], $this->getOptionFieldsConfig() ); // Add fields to the values $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'], $this->getValueFieldsConfig() ); } /** * The custom option fields config * * @return array */ protected function getOptionFieldsConfig() { $fields['is_special_offer'] = $this->getSpecialOfferFieldConfig(); return $fields; } /** * The custom option fields config * * @return array */ protected function getValueFieldsConfig() { $fields['description'] = $this->getDescriptionFieldConfig(); return $fields; } /** * Get special offer field config * * @return array */ protected function getSpecialOfferFieldConfig() { return [ 'arguments' => [ 'data' => [ 'config' => [ 'label' => __('Is Special Offer'), 'componentType' => Field::NAME, 'formElement' => Checkbox::NAME, 'dataScope' => 'is_special_offer', 'dataType' => Text::NAME, 'sortOrder' => 65, 'valueMap' => [ 'true' => '1', 'false' => '0' ], ], ], ], ]; } /** * Get description field config * * @return array */ protected function getDescriptionFieldConfig() { return [ 'arguments' => [ 'data' => [ 'config' => [ 'label' => __('Description'), 'componentType' => Field::NAME, 'formElement' => Input::NAME, 'dataType' => Text::NAME, 'dataScope' => 'description', 'sortOrder' => 41 ], ], ], ]; } }
Ce que nous devons faire ici, c'est ajouter de manière récursive une configuration nécessaire pour les champs "Est une offre spéciale" et "Description" au bon endroit. Faites attention aux deux dernières méthodes qui réalisent réellement la configuration des champs ajoutés. Pour 'Est une offre spéciale, nous utilisons une case à cocher et pour 'Description' ― saisie de texte.
Comme nos champs dans la base de données sont situés dans les champs 'catalog_product_option' et 'catalog_product_option_type_value', Magento 2 lui-même les ajoutera au formulaire à condition que nous spécifions 'dataScope' correctement.
Il est important d'utiliser un 'sortOrder' différent pour éviter de remplacer les champs standard des options personnalisables. Après avoir joué avec différentes variantes de 'sortOrder', vous pouvez organiser les champs dans l'ordre qui vous convient le mieux.
De plus, la configuration des champs vous permet d'ajouter diverses validations en ligne. Par exemple, dans notre extension Advanced Product Options, le champ 'Coût' est implémenté comme suit :
'label' => __('Cost'), 'componentType' => Field::NAME, 'formElement' => Input::NAME, 'dataScope' => 'cost', 'dataType' => Number::NAME, 'validation' => [ 'validate-number' => true, 'validate-zero-or-greater' => true, ]
Ensuite, videz le cache :
sudo -u www-data php bin/magento cache:clean
Il ne reste plus qu'à ouvrir un produit qui nous intéresse, remplir les champs nécessaires et le sauvegarder. Le résultat final ressemblera à quelque chose comme ça :
Emballer
Magento 2 offre un mécanisme extrêmement pratique d'extension des options personnalisables avec des fonctionnalités pratiquement illimitées. C'est ce que nous utilisons avec impatience dans notre extension et que nous vous recommandons certainement.