¿Cómo agregar un campo a las opciones personalizadas en Magento 2?
Publicado: 2019-07-16Todos sabéis lo cómodo que es utilizar las opciones personalizables de los productos. Tenemos un poderoso conjunto de opciones avanzadas de productos que amplía drásticamente la funcionalidad estándar de las opciones personalizables. Los campos personalizados son la base de algunas de las funciones de la extensión. Estos campos se agregan a tipos de opciones específicas, como una casilla de verificación o un área de texto.
En el artículo, haré todo lo posible para explicar cómo puede agregar los campos necesarios a la base de datos y al panel de administración de forma rápida y sencilla. Tengamos una idea.
1. Crear un nuevo módulo
Primero, creemos un módulo MageWorx_Option. Lo haremos todo usando este módulo como ejemplo.
Vamos a crear el siguiente directorio: app/code/MageWorx/Option. Para registrar un módulo, necesitaremos algunos archivos estándar:
<?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. Agregar nuestros nuevos campos a la base de datos
Por ejemplo, deseamos resaltar una de las opciones en el front-end de alguna manera. Agreguemos un campo de casilla de verificación para una opción "Es una oferta especial" y un campo de texto "Descripción" para los valores de las opciones seleccionables (menú desplegable, casilla de verificación, botón de radio, selección múltiple).
Primero, necesitaremos agregarlo a la base de datos en las tablas correspondientes. Para eso, agregue el siguiente archivo: 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(); } }
El campo "Es una oferta especial" estará deshabilitado de forma predeterminada.
A continuación, podemos instalar el módulo.
Para hacer eso, ejecute los siguientes comandos en la consola:
sudo -u www-data php bin/magento module:enable MageWorx_Option sudo -u www-data php bin/magento setup:upgrade
3. Agregue lógica para trabajar con el backend
En este punto, agreguemos el mecanismo de modificadores de grupo a nuestro módulo, que Magento 2 usa para combinar todas las funciones necesarias en una página de producto en el panel de administración.
Para eso, agreguemos el siguiente archivo:
aplicación/código/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>
Ahora es el momento de crear nuestra clase MageWorx\Option\Ui\DataProvider\Product\Form\Modifier\All, que no agrega nada nuevo por sí misma al formulario de Opciones personalizables en la página del producto. Usando la inyección de dependencia (DI), agregará los campos necesarios en la página del producto.
De hecho, nuestro conjunto de opciones avanzadas de productos agrega alrededor de 40 campos y otras estructuras complejas, que se agregan con la ayuda de más de 10 paquetes que se incluyen dentro de la extensión. Como no necesitamos una estructura tan compleja aquí, usaremos únicamente un modificador de clase:
MageWorx\Option\Ui\DataProvider\Product\Form\Modifier\Base.

Quizás se pregunte por qué especificamos el siguiente orden de clasificación = 71. Todo esto puede explicarse por la funcionalidad estándar de Magento 2, donde los campos para Opciones personalizables se agregan en orden de clasificación = 70.
A continuación, eche un vistazo a la clase MageWorx\Option\Ui\DataProvider\Product\Form\Modifier\All, que se presenta mediante un iterador regular:
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; } }
Básicamente, ahora es el momento de crear un archivo, que agregará nuestros campos al formulario de Opciones personalizables:
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 ], ], ], ]; } }
Lo que debemos hacer aquí es agregar recursivamente una configuración necesaria para los campos 'Es una oferta especial' y 'Descripción' en el lugar correcto. Preste atención a los dos últimos métodos que realmente realizan la configuración de los campos agregados. Para 'Es una oferta especial, usamos la casilla de verificación y para 'Descripción', la entrada de texto.
Como nuestros campos en la base de datos se encuentran en los campos 'catalog_product_option' y 'catalog_product_option_type_value', el propio Magento 2 los agregará al formulario siempre que especifiquemos 'dataScope' correctamente.
Es importante usar un 'orden de clasificación' diferente para evitar reemplazar los campos estándar de Opciones personalizables. Después de jugar con varias variantes de 'sortOrder', puede organizar los campos en el orden que más le convenga.
Además, la configuración de campos le permite agregar varias validaciones en línea. Por ejemplo, en nuestra extensión Opciones avanzadas de productos, el campo 'Costo' se implementa de la siguiente manera:
'label' => __('Cost'), 'componentType' => Field::NAME, 'formElement' => Input::NAME, 'dataScope' => 'cost', 'dataType' => Number::NAME, 'validation' => [ 'validate-number' => true, 'validate-zero-or-greater' => true, ]
Luego, borre el caché:
sudo -u www-data php bin/magento cache:limpiar
Solo queda abrir un producto que nos interese, rellenar los campos necesarios y guardarlo. El resultado final será algo así:

Envolver
Magento 2 ofrece un mecanismo extremadamente conveniente para expandir las opciones personalizables con una funcionalidad prácticamente ilimitada. Eso es lo que usamos con entusiasmo en nuestra extensión y sin duda lo recomendamos.