Выражение ограничения проверки формы Symfony

У меня есть форма, и мне нужно создать встроенную проверку:

$builder
        ->add('Count1', 'integer', [
            'data'        => 1,
            'constraints' => [
                new NotBlank(),
                new NotNull(),
            ],
        ])
        ->add('Count2', 'integer', [
            'constraints' => [
                new NotBlank(),
                new NotNull(),
            ],
        ])
        ->add('Count3', 'integer', [
            'data'        => 0,
            'constraints' => [
                new NotBlank(),
                new NotNull(),
            ],
        ])

Как белая встроенная проверка выражения для правил

  1. Count2> = Count1
  2. Count3 <= Count2
  3. Count2> = $ someVariable

3 ответа

Решение

Другое решение с использованием Expression Constraint для случаев 1 и 2.

use Symfony\Component\Validator\Constraints as Assert;

// ...

public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults([
        'constraints' => [
            new Assert\Expression([
                'expression' => 'value["Count2"] >= value["Count1"]',
                'message' => 'count2 must be greater than or equal to count1'
            ]),
            new Assert\Expression([
                'expression' => 'value["Count3"] <= value["Count2"]',
                'message' => 'count3 must be less than or equal to count2'
            ]),
        ],
    ]);
}

Для случая 3 вы можете использовать Assert\GreaterThanOrEqual ограничение непосредственно на Count3 поле.

Я полагаю, что ваша форма не имеет привязки объектной модели, в противном случае для чтения упомянутой документации достаточно и лучше, потому что вы можете использовать эти выражения непосредственно в своих свойствах.

Вы можете использовать CallbackValidator ( документы):

В вашем случае, чтобы снова проверить одно поле или другое, вам нужно добавить ограничение к типу формы, а не к полю:

public function setDefaultOptions(OptionsResolverInterface $resolver)
{
    $resolver->setDefaults(array(
        'constraints' => array(
            new Assert\Callback(function($data){
                // $data is instance of object (or array) with all properties
                // you can compare Count1, Count2 and Count 3 
                // and raise validation errors
            });
        )
    ));
}

Вы также можете пройти constraints вариант при создании формы, если вы не хотите устанавливать ее в setDefaultOptions,

Начиная с самого простого

3) Count2> = $ someVariable

    ->add('Count3', 'integer', [
        'data'        => 0,
        'constraints' => [
            new NotBlank(),
            new NotNull(),
            new GreaterThanOrEqual($someVariable),
        ],
    ])

1) Что касается двух первых, вы должны реализовать ограничение для области видимости, а не свойства области. И назначить эти ограничения для всей формы

public function buildForm(FormBuilderInterface $builder, array $options)
{
   $builder
    ->add('Count1', 'integer', [
        'data'        => 1,
        'constraints' => [
            new NotBlank(),
            new NotNull(),
        ],
    ])
    ->add('Count2', 'integer', [
        'constraints' => [
            new NotBlank(),
            new NotNull(),
        ],
    ])
    ->add('Count3', 'integer', [
        'data'        => 0,
        'constraints' => [
            new NotBlank(),
            new NotNull(),
        ],
    ])
}

public function setDefaultOptions(OptionsResolverInterface $resolver)
{
     $resolver->setDefaults(['constraints' => [
            new YourCustomConstraint(),
          ]]);
}

Как реализовать валидатор, смотрите в документации. Но в вашем YourCustomConstraintValidator у тебя будет что-то вроде

public function validate($value, Constraint $constraint)
{
     if ($value->getCount1() > $value->getCount2() {
           $this->context->addViolation(...);
     }
}

У меня возникла проблема со сравнением двух дат с помощью выражений Symfony.

Вот код, который работает:

 $builder->add(
            'end',
            DateTimeType::class,
            [
                'label' => 'Campaign Ends At',
                'data' => $entity->getEnd(),
                'required' => true,
                'disabled' => $disabled,
                'widget'  => 'single_text',
                'constraints' => [
                    new Assert\GreaterThan(['value' => 'today']),
                    new Assert\Expression(
                                [
                                    //here end and start are the name of two fields
                                    'expression' => 'value > this.getParent()["start"].getData()',
                                    'message' => 'my.form.error.end.date.bigger.than.start'
                                ]
                            ),
                ]

            ]
        );
Другие вопросы по тегам