Php Symfony(2.7)——>;构建表单->;将表单中另一个字段的值传递给自定义约束
我想将某个字段的值传递给另一个字段的自定义约束(->以便在自定义验证器中使用) 表单中包含一些字段:Php Symfony(2.7)——>;构建表单->;将表单中另一个字段的值传递给自定义约束,php,symfony,symfony-forms,Php,Symfony,Symfony Forms,我想将某个字段的值传递给另一个字段的自定义约束(->以便在自定义验证器中使用) 表单中包含一些字段: ... ->add('BsaKey', new \app\...\fieldTypes\RadioButtonType(), [ 'choices' => [ ... ], 'expanded' => true,
...
->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作为一个整体来使用,只是一些独立的组件
编辑: Thx,我找到了解决方案:
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);
}
}
我用计算机做了一些类似的事情。 我会检查一个字段是否大于另一个字段,请根据您的要求随意更改 样本代码
<?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);
}
}
尝试使“validate”-函数返回上下文类(任何不是当前字符串值的内容),但对我无效。尝试换行并发送消息。。。我注意到我试图使用“getTargets()”-函数获取对象作为“validate()”-function的第一个参数,但不起作用…试图使“validate”-函数返回上下文类(任何不包含当前字符串值的内容),但对我不起作用。试图换行并发送消息。。。我注意到我试图使用“getTargets()”-函数获取对象作为“validate()”-函数的第一个参数,但没有成功。。。