[ '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 ]
I am adding custom product attribute which works fine, but not able to add validate-greater-than-zero validation.
If we look at any attribute properties in Input Validation for Store Owner there are limited number of validations in select options.
validate-number,validate-digits,validate-email,validate-url,validate-alpha,validate-alphanum
These are the only validations applied in Product attribute section.
-
Please see my answer, it will be helping you to validate your attribute value.Matthéo Geoffray– Matthéo Geoffray2017年01月17日 10:14:05 +00:00Commented Jan 17, 2017 at 10:14
3 Answers 3
One of the solution is to add a backend model to your attribute which is used to format / validate your attribute value before save and/or after load.
Add a backend class :
[
'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
]
Here is an example of your custom class \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;
}
}
If you want a simple example of that kind of class you can check
\Magento\Customer\Model\Customer\Attribute\Backend\Website- all the classes which extend
\Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend - the classes into
backend_modelcolumn ineav_attributetable
EDIT
If you want a class that do nearly the same thing as you want you can take a look at the
SKU attribute validation \Magento\Catalog\Model\Product\Attribute\Backend\SkuI also added the method in the example class
EDIT
Another solution (maybe not the best one) is to create a plugin on the function
\Magento\Eav\Helper\Data::getFrontendClasses and add your frontend class here that can be validated in front.
-
Thanks for your reply but would it be possible to apply frontend validation.Amit Singh– Amit Singh2017年01月17日 12:04:46 +00:00Commented Jan 17, 2017 at 12:04
-
If you take a look at your attribute line in
eav_attributetable in the columnfrontend_classis thee the valuevalidate-greater-than-zero?Matthéo Geoffray– Matthéo Geoffray2017年01月17日 12:28:48 +00:00Commented Jan 17, 2017 at 12:28 -
Yes but it doesn't work. These are the only classes which works
validate-number,validate-digits,validate-email,validate-url,validate-alpha,validate-alphanum.Amit Singh– Amit Singh2017年01月17日 13:18:23 +00:00Commented Jan 17, 2017 at 13:18 -
1Can you try my second edit, to add your custom frontend classes ?Matthéo Geoffray– Matthéo Geoffray2017年01月17日 17:06:54 +00:00Commented Jan 17, 2017 at 17:06
-
OK great ! Can you apply the bounty as well please ? Thank you.Matthéo Geoffray– Matthéo Geoffray2017年01月19日 09:07:49 +00:00Commented Jan 19, 2017 at 9:07
With the help of Matthéo Geoffray, this is what I did to apply frontend validation for custom attributes.
[
'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
]
This is the custom attribute in install script.
I added plugin in 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>
Here is the plugin code.
<?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;
}
}
Basically in \Magento\Catalog\Ui\DataProvider\CatalogEavValidationRules, the method called mapRules only matches the frontend class against limited number of validation rules. To apply more validation rules we need to append rules using plugin.
For server side validation, Please refer to Matthéo Geoffray answer.
I'm not sure it could be possible from install script.
But I'm sure it's possible if you will create "before listener plugin" with function beforeSave() and check value there.
Explore related questions
See similar questions with these tags.