Правило When
Правило When из пространства имён
Symfony\Component\Validator\Constraints
применяется в формах Symfony для условной
валидации. Оно принимает выражение
expression, которое вычисляется при
проверке формы. Если выражение возвращает
true, то к полю применяются ограничения,
переданные в параметре constraints. Если
выражение возвращает false, валидация
по этим ограничениям не выполняется.
Правило When удобно использовать, когда
одно поле должно быть обязательным только
при определённом значении другого поля.
Например, поле companyName обязательно,
только если пользователь выбрал тип
'company'.
Синтаксис
use Symfony\Component\Validator\Constraints\When;
new When([
'expression' => 'this.type == "company"',
'constraints' => [
new NotBlank(),
],
])
Параметр expression задаёт выражение,
которое вычисляется в контексте валидируемого
объекта. Параметр constraints содержит
массив ограничений, применяемых при истинном
выражении.
Пример
Давайте создадим форму с полем type и
полем companyName. Поле
companyName будет обязательным только
при значении type равном 'company':
<?php
namespace App\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\When;
class UserType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('type', ChoiceType::class, [
'choices' => [
'Person' => 'person',
'Company' => 'company',
],
])
->add('companyName', TextType::class, [
'constraints' => [
new When([
'expression' => 'this.type == "company"',
'constraints' => [
new NotBlank([
'message' => 'Company name is required.',
]),
],
]),
],
]);
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => null,
]);
}
}
?>
Теперь создадим контроллер, который обрабатывает форму и выводит результат валидации:
<?php
namespace App\Controller;
use App\Form\UserType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
class UserController extends AbstractController
{
#[Route('/user', name: 'user_form')]
public function index(Request $request): Response
{
$form = $this->createForm(UserType::class);
$form->handleRequest($request);
if ($form->isSubmitted()) {
if ($form->isValid()) {
$data = $form->getData();
return new Response('Valid: ' . $data['type'] . ' / ' . $data['companyName']);
}
$errors = $form->getErrors(true);
$messages = [];
foreach ($errors as $error) {
$messages[] = $error->getMessage();
}
return new Response(implode(', ', $messages));
}
return $this->render('user/index.html.twig', [
'form' => $form->createView(),
]);
}
}
?>
Создадим Twig-шаблон для отображения формы:
{{ form_start(form) }}
{{ form_row(form.type) }}
{{ form_row(form.companyName) }}
<button type="submit">Send</button>
{{ form_end(form) }}
Если отправить форму со значением type
равным 'person' и пустым полем
companyName, форма будет валидной.
Результат выполнения кода:
"Valid: person / "
Пример
Давайте отправим форму со значением type
равным 'company' и пустым полем
companyName. Теперь сработает правило
When и ограничение NotBlank:
"Company name is required."
Если же заполнить поле companyName
значением 'abcde', форма снова станет
валидной:
"Valid: company / abcde"
Пример
Правило When можно комбинировать с
разными ограничениями. Давайте сделаем поле
email обязательным и проверяемым на
корректность только при типе 'company':
<?php
namespace App\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\Email;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\When;
class CompanyType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('type', ChoiceType::class, [
'choices' => [
'Person' => 'person',
'Company' => 'company',
],
])
->add('name', TextType::class)
->add('email', EmailType::class, [
'constraints' => [
new When([
'expression' => 'this.type == "company"',
'constraints' => [
new NotBlank(),
new Email(),
],
]),
],
]);
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => null,
]);
}
}
?>
Если отправить форму с типом 'company'
и некорректным email 'not-an-email',
сработает ограничение Email:
"This value is not a valid email address."
Если же указать тип 'person', поле
email не будет валидироваться вовсе,
даже если оно пустое или содержит некорректное
значение.