在我的Form
我有Fieldset
,其中包含两个元素foo
和bar
。他们的业务规则是,必须设置一个。因此,当设置foo
或bar
时,字段集有效,而当没有设置时,字段集无效。
我解决了这个问题如下:
public function getInputFilterSpecification()
{
return [
'foo' => [
'required' => empty($this->get('bar')->getValue())
],
'bar' => [
'required' => empty($this->get('foo')->getValue())
],
];
}
工作。但是错误消息仍然存在问题:如果bot字段为空,则用户为每个字段获取消息“值是必需的且不能为空”。用户认为,他必须填写这两个字段。
如何自定义required
字段的错误消息,以便显示正确的消息,例如“foo的值是必需的,如果未设置条形,则不能为空“。并且“条形值是必需的,如果没有设置foo,则不能为空。”?
答案 0 :(得分:0)
您可以通过扩展默认链
来创建自定义ValidatorChain然后您可以覆盖此方法:
/**
* Returns true if and only if $value passes all validations in the chain
*
* Validators are run in the order in which they were added to the chain (FIFO).
*
* @param mixed $value
* @param mixed $context Extra "context" to provide the validator
* @return bool
*/
public function isValid($value, $context = null)
{ .. }
默认情况下,如果所有验证器返回true,则此方法仅返回true,但它也可以访问上下文 - 这意味着您也可以获取所有其他字段值。
修改逻辑然后检查其中一个验证器是否为true都很简单。
然后,您只需附加您想要的所有字段"其中一个是必需的"
答案 1 :(得分:-1)
你最终会得到一个像这样的自定义验证器:
ViewDidLoad()
那么如何使用它:
class MyCustomValidator extends ZendAbstractValidator
{
const FIELDS_EMPTY = 'fieldsEmpty';
/**
* Error messages
*
* @var array
*/
protected $abstractMessageTemplates = [
self::FIELDS_EMPTY => "Vale for %field1% is required and can't be empty, if %field2% is not set.",
];
/**
* Variables which can be used in the message templates
*
* @var array
*/
protected $abstractMessageVariables = [
'field1' => 'field1',
'field2' => 'field2',
];
/**
* Value of the field
* @var mixed
*/
protected $value;
/**
* Name of the first field to check, which the validator is bind to
* @var mixed
*/
protected $field1;
/**
* Name of the second field to check
* @var string
*/
protected $field2;
/**
* MyCustomValidator constructor.
*
* @param array|null|\Traversable $options
*
* @throws \Exception
*/
public function __construct($options)
{
if ($options instanceof Traversable) {
$options = ArrayUtils::iteratorToArray($options);
}
if (!array_key_exists('field1', $options) || !array_key_exists('field2', $options)) {
throw new \Exception('Options should include both fields to be defined within the form context');
}
$this->field1 = $options['field1'];
$this->field2 = $options['field2'];
parent::__construct($options);
}
/**
* Returns true if and only if $value meets the validation requirements
* If $value fails validation, then this method returns false, and
* getMessages() will return an array of messages that explain why the
* validation failed.
*
* @param mixed $value
* @param array $context
*
* @return bool
*/
public function isValid($value, $context = [])
{
$this->setValue($value);
if (empty($value) && (array_key_exists($this->field2, $context) || empty($context[$this->field2]))) {
$this->error(self::FIELDS_EMPTY);
return false;
}
return true;
}
}
对于那些不知道如何注册MyCustomValidator的人 - 在module.config.php中或使用Module.php中的public function getInputFilterSpecification()
{
return [
'foo' => [
'validators' => [
[
'name' => MyCustomValidator::class,
'options' => [
'field1' => 'foo',
'field2' => 'bar',
]
]
]
],
'bar' => [
'validators' => [
[
'name' => MyCustomValidator::class,
'options' => [
'field1' => 'bar',
'field2' => 'foo',
]
]
]
],
];
}
。不要同时使用它们,不管是其中之一:
如何在module.config.php中注册
public function getValidatorConfig()
如何在你的module.php中注册:
'validators' => array(
'factories' => array(
MyCustomValidator::class => MyCustomValidatorFactory::class,
),
),
工厂类:
/**
* Expected to return \Zend\ServiceManager\Config object or array to
* seed such an object.
* @return array|\Zend\ServiceManager\Config
*/
public function getValidatorConfig()
{
return [
'aliases' => [
'myCustomValidator' => MyCustomValidator::class,
'MyCustomValidator' => MyCustomValidator::class,
'mycustomvalidator' => MyCustomValidator::class,
],
'factories' => [
MyCustomValidator::class => MyCustomValidatorFactory::class,
],
];
}
请注意,我保持验证器class MyCustomValidatorFactory implements FactoryInterface, MutableCreationOptionsInterface
{
/**
* Options for the InputFilter
*
* @var array
*/
protected $options;
/**
* Create InputFilter
*
* @param ServiceLocatorInterface $serviceLocator
*
* @return BlockChangeOnSerialsValidator
*/
public function createService(ServiceLocatorInterface $serviceLocator)
{
return new MyCustomValidator($this->options);
}
/**
* Set creation options
*
* @param array $options
*
* @return void
*/
public function setCreationOptions(array $options)
{
$this->setOptions($options);
}
/**
* Set options
*
* @param array $options
*/
public function setOptions(array $options)
{
$this->options = $options;
}
}
方法非常简单,因为我不确定它是否覆盖了您的情况,但这是为了帮助您朝着正确的方向前进。但是可以做的改进是重用NotEmpty验证器来检查字段是否为空。
请注意,当您致电isValid()
时,isValid($value, $context = null)
表单中的上下文是formData。