【问题标题】:Symfony (2.7) -> Building a form -> pass a value from another field in the form to a custom ConstraintSymfony (2.7) -> 构建表单 -> 将表单中另一个字段的值传递给自定义约束
【发布时间】:2016-10-12 11:10:23
【问题描述】:

我想将某个字段的值传递给另一个字段的自定义约束(->在自定义验证器中使用它)

带有一些字段的表单:

...
            ->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 symfony symfony-forms


    【解决方案1】:

    我使用custom constraint 做了一些类似的事情。 我会检查一个字段是否大于另一个字段,请随意将其更改为您的要求。

    示例代码;

    <?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]
    

    【讨论】:

    • 试图让“验证”函数返回上下文类(任何东西都不是当前的字符串值),但对我没有用。
    • 试图换行并发送消息...我提到我尝试使用“getTargets()”函数来获取对象作为“validate()”函数的第一个参数,但是没用...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-06
    • 2018-02-17
    • 1970-01-01
    相关资源
    最近更新 更多