我想传递一些字段的值给另一个字段的自定义约束(->在自定义Validator中使用它)
带有一些字段的表单:
...
->add('BsaKey', new 'app'...'fieldTypes'RadioButtonType(), [
'choices' => [
...
],
'expanded' => true,
'multiple' => false,
...
])
->add('MeteringCodes', 'collection', [
'type' => new 'app'...'formTypes'MeteringCodeType(),
'allow_add' => true,
'label' => false,
'options' => ['label' => $this->lang->get('MeteringCode.Caption')],
'constraints' => new 'app'...'validators'NoIdenticMeteringCodes()
])
...
现在我需要将BsaKey的值传递给MeteringCodeType的自定义约束:
class MeteringCodeType extends 'Symfony'Component'Form'AbstractType
{
public function buildForm('Symfony'Component'Form'FormBuilderInterface $builder, array $options)
{
$builder->add('meteringCode', 'text', [
'...' => '...',
'constraints' => new 'app'...'MeteringCodeConstraint(['param' => 'VALUE_OF_BsaKey'])
]);
}
}
我怎样才能做到这一点?
注:我不使用Symfony作为一个整体,只是一些独立的组件…
编辑:
谢谢,我找到了解决方案:
class MeteringCodeValidator extends 'Symfony'Component'Validator'ConstraintValidator
{
public function validate($value, 'Symfony'Component'Validator'Constraint $constraint)
{
$BsaKey = $this->context->getRoot()->get('BsaKey')->getData();
...
}
}
似乎独立于"getTargets()"函数返回的选项。
我使用自定义约束做了类似的事情。我的检查一个字段大于另一个字段,请随意更改它以满足您的要求。
示例代码;
<?php
// src/AppBundle/Validator/Constraints/FieldCompare.php
namespace AppBundle'Validator'Constraints;
use Symfony'Component'Validator'Constraint;
/**
* @Annotation
*/
class FieldCompare extends Constraint
{
/**
* Error Message
* @access public
* @var string - with placeholders [field1,field2]
*/
public $message = 'Field field2 must be greater than field1 ';
/**
* Form fields
* @access public
* @var array
*/
public $fields = array();
/**
* Class accessors (getters) for the fields.
* @access public
* @var array
*/
public $properties = array();
/**
* Error Path
* @var string
*/
public $errorPath;
public function __construct($options = null)
{
parent::__construct($options);
// check fields is an array
if (!is_array($this->fields) && !is_string($this->fields)) {
throw new UnexpectedTypeException($this->fields, 'array');
}
// make sure there are two of them
if (2 != count($this->fields)) {
throw new ConstraintDefinitionException("Two fields must be specified.");
}
// make sure they are strings
foreach ($this->fields as $f) {
if (null !== $this->errorPath && !is_int()) {
throw new UnexpectedTypeException($this->errorPath, 'integer or null');
}
}
}
/**
* getTargets()
*
* Set traget (so can be used against the class).
* @access public
* @return type
*/
public function getTargets()
{
return self::CLASS_CONSTRAINT;
}
}
<?php
// src/AppBundle/Validator/Constraints/FieldCompareValidator.php
namespace AppBundle'Validator'Constraints;
use Symfony'Component'Validator'Constraint;
use Symfony'Component'Validator'ConstraintValidator;
class FieldCompareValidator extends ConstraintValidator {
public function validate($protocol, Constraint $constraint)
{
$fields = (array) $constraint->fields;
$properties = (array) $constraint->properties;
if ($protocol->$properties[0]() >= $protocol->$properties[1]()) {
$this->context->addViolationAt($fields[1], $constraint->message,
array(
'field1' => $this->prettyField($fields[0]),
'field2' => $this->prettyField($fields[1])
), null);
}
}
private function prettyField($field)
{
if (strstr($field, '_')) {
$pretty = str_replace('_', ' ', $field);
} else {
// is camelCase
$converted = preg_replace('/(?!^)[[:upper:]]+/',' '0', $field);
if (is_array($converted)) {
$pretty = implode(' ', $converted);
} else {
$pretty = $converted;
}
}
return ucwords($pretty);
}
}
下面是我如何应用验证器(yaml格式);
AppBundle'Model'Foo:
constraints:
- AppBundle'Validator'Constraints'FieldCompare:
fields: [min_lead_time, max_lead_time]
properties: [getminLeadtime, getmaxLeadtime]
groups: [add]