Magento 2 agrega validación de atributo de producto personalizado desde el script de instalación

17
[
    'type' => 'int',
    'backend' => '',
    'frontend' => '',
    'label' => 'XXXX',
    'input' => 'texto',
    'frontend_class' => 'validar-mayor-que-cero',
    'source' => '',
    'global' => \ Magento \ Eav \ Model \ Entity \ Attribute \ ScopedAttributeInterface :: SCOPE_GLOBAL,
    'visible' => verdadero,
    'required' => verdadero,
    'user_defined' => false,
    'default' => 0,
    'searchable' => falso,
    'filterable' => verdadero,
    'comparable' => falso,
    'visible_on_front' => falso,
    'used_in_product_listing' => verdadero,
    'unique' => false
]

Estoy agregando un atributo de producto personalizado que funciona bien, pero no puedo agregar validate-greater-than-zerovalidación.

Si observamos las propiedades de los atributos, Input Validation for Store Ownerhay un número limitado de validaciones en las opciones de selección.

validate-number, validate-digits, validate-email, validate-url, validate-alpha,validate-alphanum

Estas son las únicas validaciones aplicadas en la sección de atributos del Producto.

Amit Singh
fuente
Por favor, vea mi respuesta, lo ayudará a validar el valor de su atributo.
Matthéo Geoffray

Respuestas:

13

Una de las soluciones es agregar un backend modelatributo a su atributo que se utiliza para formatear / validar el valor de su atributo antes de guardarlo y / o después de la carga.

Agregar una clase de back-end:

[
    'type' => 'int',
    'backend' => '\Foo\Bar\Model\Attribute\Backend\YourAttribute',
    'frontend' => '',
    'label' => 'XXXX',
    'input' => 'text',
    'frontend_class' => 'validate-greater-than-zero',
    'source' => '',
    'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL,
    'visible' => true,
    'required' => true,
    'user_defined' => false,
    'default' => 0,
    'searchable' => false,
    'filterable' => true,
    'comparable' => false,
    'visible_on_front' => false,
    'used_in_product_listing' => true,
    'unique' => false
]

Aquí hay un ejemplo de su clase personalizada \Foo\Bar\Model\Attribute\Backend\YourAttribute

<?php

namespace Foo\Bar\Model\Attribute\Backend;

/**
 * Class YourAttribute
 */
class YourAttribute extends \Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend
{

    /**
     * @var int $minimumValueLength
     */
    protected $minimumValueLength = 0;

    /**
     * @param \Magento\Framework\DataObject $object
     *
     * @return $this
     */
    public function afterLoad($object)
    {
        // your after load logic

        return parent::afterLoad($object);
    }

    /**
     * @param \Magento\Framework\DataObject $object
     *
     * @return $this
     */
    public function beforeSave($object)
    {
        $this->validateLength($object);

        return parent::beforeSave($object);
    }

    /**
     * Validate length
     *
     * @param \Magento\Framework\DataObject $object
     *
     * @return bool
     * @throws \Magento\Framework\Exception\LocalizedException
     */
    public function validateLength($object)
    {
        /** @var string $attributeCode */
        $attributeCode = $this->getAttribute()->getAttributeCode();
        /** @var int $value */
        $value = (int)$object->getData($attributeCode);
        /** @var int $minimumValueLength */
        $minimumValueLength = $this->getMinimumValueLength();

        if ($this->getAttribute()->getIsRequired() && $value <= $minimumValueLength) {
            throw new \Magento\Framework\Exception\LocalizedException(
                __('The value of attribute "%1" must be greater than %2', $attributeCode, $minimumValueLength)
            );
        }

        return true;
    }

    /**
     * Get minimum attribute value length
     * 
     * @return int
     */
    public function getMinimumValueLength()
    {
        return $this->minimumValueLength;
    }
}

Si desea un ejemplo simple de ese tipo de clase, puede consultar

  • \Magento\Customer\Model\Customer\Attribute\Backend\Website
  • todas las clases que se extienden \Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend
  • las clases en backend_modelcolumna en la eav_attributetabla


EDITAR
Si desea una clase que haga casi lo mismo que desea, puede echar un vistazo a la SKUvalidación de atributos \Magento\Catalog\Model\Product\Attribute\Backend\Sku
También agregué el método en la clase de ejemplo


EDITAR
Otra solución (tal vez no la mejor) es crear un complemento en la función \Magento\Eav\Helper\Data::getFrontendClassesy agregar su clase frontend aquí que pueda validarse al frente.

Matthéo Geoffray
fuente
Gracias por su respuesta, pero ¿sería posible aplicar la validación frontend?
Amit Singh
Si observa la línea de atributos en la eav_attributetabla de la columna, ¿ frontend_classes el valor validate-greater-than-zero?
Matthéo Geoffray
Si pero no funciona. Estas son las únicas clases que funciona validate-number, validate-digits, validate-email, validate-url, validate-alpha, validate-alphanum.
Amit Singh
1
¿Puedes probar mi segunda edición para agregar tus clases frontend personalizadas?
Matthéo Geoffray
Lo hice usando el complemento, gracias por la pista
Amit Singh
12

Con la ayuda de Matthéo Geoffray, esto es lo que hice para aplicar la validación frontend para atributos personalizados.

[
    'type' => 'int',
    'backend' => '',
    'frontend' => '',
    'label' => 'XXXX',
    'input' => 'text',
    'frontend_class' => 'validate-greater-than-zero',
    'source' => '',
    'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL,
    'visible' => true,
    'required' => true,
    'user_defined' => false,
    'default' => 0,
    'searchable' => false,
    'filterable' => true,
    'comparable' => false,
    'visible_on_front' => false,
    'used_in_product_listing' => true,
    'unique' => false
]

Este es el atributo personalizado en el script de instalación.

Agregué el complemento en di.xml

<type name="Magento\Catalog\Ui\DataProvider\CatalogEavValidationRules">
      <plugin name="namespace_custom_validation_for_product_attribute" type="Namespace\Module\Model\Plugin\Product\ValidationRules"/>
</type>

Aquí está el código del complemento.

<?php

namespace Namespace\Module\Model\Plugin\Product;

use Closure;

class ValidationRules
{

    /**
     * @param \Magento\Catalog\Ui\DataProvider\CatalogEavValidationRules $rulesObject
     * @param callable $proceed
     * @param \Magento\Catalog\Api\Data\ProductAttributeInterface $attribute,
     * @param array $data
     * @return array
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
     */
    public function aroundBuild(
        \Magento\Catalog\Ui\DataProvider\CatalogEavValidationRules $rulesObject,
        Closure $proceed,
        \Magento\Catalog\Api\Data\ProductAttributeInterface $attribute,
        array $data
    ){
        $rules = $proceed($attribute,$data);
        if($attribute->getAttributeCode() == 'xyz'){ //custom filter
            $validationClasses = explode(' ', $attribute->getFrontendClass());
            foreach ($validationClasses as $class) {
                $rules[$class] = true;
            }
        }
        return $rules;
    }
}

Básicamente \Magento\Catalog\Ui\DataProvider\CatalogEavValidationRules, el método llamado mapRulessolo hace coincidir la clase frontend con un número limitado de reglas de validación. Para aplicar más reglas de validación, necesitamos agregar reglas usando el complemento.

Para la validación del lado del servidor, consulte la Matthéo Geoffrayrespuesta.

Amit Singh
fuente
3

No estoy seguro de que sea posible desde el script de instalación. Pero estoy seguro de que es posible si va a crear "antes del complemento de escucha" con la función beforeSave()y comprobar el valor allí.

Fred Orosko Dias
fuente