Magento 2 adiciona validação de atributo de produto personalizado a partir do script de instalação

17
[
    'type' => 'int',
    'back-end' => '',
    'frontend' => '',
    'label' => 'XXXX',
    'input' => 'texto',
    'frontend_class' => 'validar maior que zero',
    'fonte' => '',
    'global' => \ Magento \ Eav \ Modelo \ Entidade \ Atributo \ ScopedAttributeInterface :: SCOPE_GLOBAL,
    'visible' => true,
    'required' => true,
    'user_defined' => false,
    'padrão' => 0,
    'pesquisável' => falso,
    'filtrável' => verdadeiro,
    'comparável' => falso,
    'visible_on_front' => false,
    'used_in_product_listing' => true,
    'exclusivo' => falso
]

Estou adicionando atributo de produto personalizado que funciona bem, mas não é possível adicionar validate-greater-than-zerovalidação.

Se olharmos para qualquer propriedade de atributo, Input Validation for Store Ownerhá um número limitado de validações nas opções selecionadas.

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

Essas são as únicas validações aplicadas na seção de atributo Produto.

Amit Singh
fonte
Por favor, veja minha resposta, isso ajudará você a validar seu valor de atributo.
Matthéo Geoffray

Respostas:

13

Uma das soluções é adicionar um backend modelao seu atributo, que é usado para formatar / validar o valor do seu atributo antes de salvar e / ou após o carregamento.

Adicione uma classe 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
]

Aqui está um exemplo de sua classe 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;
    }
}

Se você quiser um exemplo simples desse tipo de classe, verifique

  • \Magento\Customer\Model\Customer\Attribute\Backend\Website
  • todas as classes que se estendem \Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend
  • as classes em backend_modelcoluna na eav_attributetabela


EDIT
Se você quiser uma classe que faça quase a mesma coisa que você deseja, pode dar uma olhada na SKUvalidação de atributo \Magento\Catalog\Model\Product\Attribute\Backend\Sku
. Também adicionei o método na classe de exemplo


EDIT
Outra solução (talvez não a melhor) é criar um plugin na função \Magento\Eav\Helper\Data::getFrontendClassese adicionar aqui a sua classe frontend que pode ser validada na frente.

Matthéo Geoffray
fonte
Obrigado pela sua resposta, mas seria possível aplicar a validação de front-end.
Amit Singh
Se você der uma olhada na sua linha de atributos na eav_attributetabela da coluna, frontend_classé este o valor validate-greater-than-zero?
Matthéo Geoffray 17/01
Sim, mas não funciona. Estas são as únicas classes que trabalha validate-number, validate-digits, validate-email, validate-url, validate-alpha, validate-alphanum.
Amit Singh
1
Você pode tentar minha segunda edição , para adicionar suas classes de front-end personalizadas?
Matthéo Geoffray 17/01
Eu fiz isso usando o plugin, obrigado pela dica
Amit Singh
12

Com a ajuda de Matthéo Geoffray, foi o que fiz para aplicar a validação de front-end 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 é o atributo customizado no script de instalação.

Adicionei plugin no 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>

Aqui está o código do plugin.

<?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;
    }
}

Basicamente \Magento\Catalog\Ui\DataProvider\CatalogEavValidationRules, o método chamado mapRulescorresponde apenas à classe frontend contra um número limitado de regras de validação. Para aplicar mais regras de validação, precisamos anexar regras usando o plugin.

Para validação no servidor, consulte a Matthéo Geoffrayresposta.

Amit Singh
fonte
3

Não sei se isso pode ser possível no script de instalação. Mas tenho certeza que é possível se você criar "antes do plug-in do ouvinte" com a função beforeSave()e verificar o valor lá.

Fred Orosko Dias
fonte