Події форми

Дата оновлення перекладу 2024-05-27

Події форми

Компонент Form надає структурований прроцес, щоб дозволити вам налаштувати ваші форми, використовуючи компонент EventDispatcher. Використовуючи події форми, ви можете змінювати інформацію або поля на різних етапах робочого процесу: від наповнення форми до відправки даних з запиту.

Наприклад, якщо вам потрібно додати поле, залежно від значень запиту, ви можете зареєструвати слухача подій до події FormEvents::PRE_SUBMIT таким чиномs:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// ...

use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;

$listener = function (FormEvent $event): void {
    // ...
};

$form = $formFactory->createBuilder()
    // ... add form fields
    ->addEventListener(FormEvents::PRE_SUBMIT, $listener);

// ...

Робочий процес форми

У життєвому циклі форми є два моменти, коли дані форми можуть бути оновлені:

  1. Під час попереднього заповнення (setData()) при створенні форми;
  2. При обробці відправки форми (handleRequest()) для оновлення даних форми на основі введених користувачем значень.

1) Попереднє заповнення форми (FormEvents::PRE_SET_DATA і FormEvents::POST_SET_DATA)

Під час попереднього заповення форми, оголошуються дві події, коли викликається метод Form::setData(): FormEvents::PRE_SET_DATA і FormEvents::POST_SET_DATA.

A) Подія FormEvents::PRE_SET_DATA

Подія FormEvents::PRE_SET_DATA оголошується на початку методу Form::setData(). Вона використовується для зміни даних, наданих під час попереднього заповнення з FormEvent::setData(). Метод Form::setData() заблоковано, так як подія оголошується з нього і викличе виключення, якщо буде викликана зі слухача.

??? ????? ????????
???? ????? ???????? ????, ??????????? ? setData()
???????? ???? ????? null
????????????? ???? ????? null
???? ????????? ????? null

See also

Побачити всі події форм одночасно ви можете в Інформаційній таблиці про події форм .

Тип форми Symfony\Component\Form\Extension\Core\Type\CollectionType покладається на підписника Symfony\Component\Form\Extension\Core\EventListener\ResizeFormListener, що слухає подію FormEvents::PRE_SET_DATA для того, щоб перевпорядквати поля форми, в залежності від даних з обʼєкта попереднього заповнення, шляхом видалення або додавання всіх рядків форми

B) Подія FormEvents::POST_SET_DATA

Подія FormEvents::POST_SET_DATA оголошується наприкінці методу Form::setData(). Ця подія може бути використана для зміни форми, залежно від заповнених даних (динамічне додавання або видалення полів).

??? ????? ????????
???? ????? ???????? ????, ??????????? ? setData()
???????? ???? ????? ???????? ????, ??????????? ? setData()
????????????? ???? ????? ???????? ????, ??????????? ?? ????????? ?????????? ?????????????
???? ????????? ????? ????????????? ????, ??????????? ?? ????????? ????????????? ?????????

See also

Побачити всі події форм одночасно ви можете в Інформаційній таблиці про події форм .

Клас Symfony\Component\Form\Extension\DataCollector\EventListener\DataCollectorListener підписаний для прослуховування події FormEvents::POST_SET_DATA, щоб збирати інформацію про форми з денормалізованих модельних даних та даних перегляду.

2) Відправка форми (FormEvents::PRE_SUBMIT, FormEvents::SUBMIT і FormEvents::POST_SUBMIT)

При виклику методу Form::handleRequest() або Form::submit(), оголошуються три події: FormEvents::PRE_SUBMIT, FormEvents::SUBMIT, FormEvents::POST_SUBMIT.

A) Подія FormEvents::PRE_SUBMIT

Подія FormEvents::PRE_SUBMIT оголошується на початку методу Form::submit().

Вона може бути використана для:

  • Зміни даних із запиту, до відправки даних у форму;
  • Додавання або видалення полів форми, до відправки даних у форму.
??? ????? ????????
???? ????? ???? ? ??????
???????? ???? ????? ?? ? ????, ?? ? ? FormEvents::POST_SET_DATA
????????????? ???? ????? ?? ? ????, ?? ? ? FormEvents::POST_SET_DATA
???? ????????? ????? ?? ? ????, ?? ? ? FormEvents::POST_SET_DATA

See also

Побачити всі події форм одночасно ви можете в Інформаційній таблиці про події форм .

Підписник Symfony\Component\Form\Extension\Core\EventListener\TrimListener підписується на подію FormEvents::PRE_SUBMIT, щоб обрізати дані запиту (для значень рядків). Підписник Symfony\Component\Form\Extension\Csrf\EventListener\CsrfValidationListener підписується на подію FormEvents::PRE_SUBMIT, щоб валідувати CSRF-токен.

B) Подія FormEvents::SUBMIT

Подія FormEvents::SUBMIT оголошується прямо перед тим, як метод Form::submit() перетворює нормалізовані дані на модельні дані та дані перегляду.

Вона може бути використана для зміни даних з нормалізованого представлення даних.

??? ????? ????????
???? ????? ???? ? ??????, ???????? ??????????? ?? ?????? ? ????????????? ?????????????
???????? ???? ????? ?? ? ????, ?? ? ? FormEvents::POST_SET_DATA
????????????? ???? ????? ?? ? ????, ?? ? ? FormEvents::POST_SET_DATA
???? ????????? ????? ?? ? ????, ?? ? ? FormEvents::POST_SET_DATA

See also

Побачити всі події форм одночасно ви можете в Інформаційній таблиці про події форм .

Caution

На цьому етапі ви не можете додавати або видаляти поля з форми.

Symfony\Component\Form\Extension\Core\EventListener\FixUrlProtocolListener підписується на подію FormEvents::SUBMIT, щоб додати протоколлл за замовчуванням до полів URL, які були відправлені без протоколу.

C) Подія FormEvents::POST_SUBMIT

Подія FormEvents::POST_SUBMIT оголошується після Form::submit(), коли були денормалізовані модельні дані та дані перегляду.

Вона може бути використана, щоб вилучати дані після денормалізації.

??? ????? ????????
???? ????? ????????????? ????, ??????????? ?? ????????? ????????????? ?????????
???????? ???? ????? ????????????? ????, ???????? ??????????? ?? ????????? ?????????? ?????????????
????????????? ???? ????? ???? ? ??????, ???????? ??????????? ? ?????? ?? ????????? ????????????? ?????????
???? ????????? ????? ????????????? ????, ??????????? ?? ????????? ????????????? ?????????

See also

Побачити всі події форм одночасно ви можете в Інформаційній таблиці про події форм .

Caution

На цьому етапі ви не можете додавати або видаляти поля з форми.

Symfony\Component\Form\Extension\DataCollector\EventListener\DataCollectorListener підписується на подію FormEvents::POST_SUBMIT, щоб збирати інформацію про форми. Symfony\Component\Form\Extension\Validator\EventListener\ValidationListener підписується на подію FormEvents::POST_SUBMIT, щоб автоматично валідувати денормалізований обʼєкт.

Реєстрація слухачів або підписників подій

Для того, щоб мати можливість використовувати події форми, вам потрібно створити слухача або підписника подій та зареєструвати йогог у події.

Імʼя кожної події "форми" визначається як константа в класі FormEvents. Додатково, кожному зворотному виклику події (метод слухача або підписника) передається один аргумент, який є екземпляром класу FormEvent. Обʼєкт події містить посилання на поточний стан форми та поточні дані, що обробляються.

???? ????????? FormEvents ???? ?????
form.pre_set_data FormEvents::PRE_SET_DATA ???????? ????
form.post_set_data FormEvents::POST_SET_DATA ???????? ????
form.pre_submit FormEvents::PRE_SUBMIT ???? ??????
form.submit FormEvents::SUBMIT ????????????? ????
form.post_submit FormEvents::POST_SUBMIT ???? ?????????

Слухачі подій

Слухач подій може бути будь-яким типом валідного викликаного.

Створення та привʼязка слухача подій - це дуже просто:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// ...

use Symfony\Component\Form\Event\PreSubmitEvent;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormEvents;

$form = $formFactory->createBuilder()
    ->add('username', TextType::class)
    ->add('showEmail', CheckboxType::class)
    ->addEventListener(FormEvents::PRE_SUBMIT, function (PreSubmitEvent $event): void {
        $user = $event->getData();
        $form = $event->getForm();

        if (!$user) {
            return;
        }

        // Перевіряє, чи обрав користувач відображати його електронну пошту.
        // Якщо дані були відправлені раніше, додаткове значення, включене
        // у змінних запиту, повинно бути видалене.
        if (isset($user['showEmail']) && $user['showEmail']) {
            $form->add('email', EmailType::class);
        } else {
            unset($user['email']);
            $event->setData($user);
        }
    })
    ->getForm();

// ...

Коли ви вже створити клас типу форми, ви можете використовувати один з його методів в якості зворотного виклику для кращої читаності:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// src/Form/SubscriptionType.php
namespace App\Form;

use Symfony\Component\Form\Event\PreSetDataEvent;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormEvents;

// ...
class SubscriptionType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('username', TextType::class)
            ->add('showEmail', CheckboxType::class)
            ->addEventListener(
                FormEvents::PRE_SET_DATA,
                [$this, 'onPreSetData']
            )
        ;
    }

    public function onPreSetData(PreSetDataEvent $event): void
    {
        // ...
    }
}

Підписники подій

Підписники подій мають різні застосування:

  • Покращення читаності;
  • Прослуховування декількох подій;
  • Регрупування декількох слухачів всередині одного класу.

    // src/Form/EventListener/AddEmailFieldListener.php namespace AppFormEventListener;

    use SymfonyComponentEventDispatcherEventSubscriberInterface; use SymfonyComponentFormEventPreSetDataEvent; use SymfonyComponentFormEventPreSubmitEvent; use SymfonyComponentFormExtensionCoreTypeEmailType; use SymfonyComponentFormFormEvents;

    class AddEmailFieldListener implements EventSubscriberInterface { public static function getSubscribedEvents(): array { return [ FormEvents::PRE_SET_DATA => 'onPreSetData', FormEvents::PRE_SUBMIT => 'onPreSubmit', ]; }

    public function onPreSetData(PreSetDataEvent $event): void { $user = $event->getData(); $form = $event->getForm();

    // Перевіряє, чи обрав користувач з початкових даних // відображати свою електронну пошту if (true === $user->isShowEmail()) { $form->add('email', EmailType::class); }

    }

    public function onPreSubmit(PreSubmitEvent $event): void { $user = $event->getData(); $form = $event->getForm();

    if (!$user) {
    return;

    }

    // Перевіряє, чи обрав користувач відображати свою електронну пошту. // Якщо дані були відправлені раніше, додаткове значення, включене // у змінних запиту, має бути видалене. if (isset($user['showEmail']) && $user['showEmail']) { $form->add('email', EmailType::class); } else { unset($user['email']); $event->setData($user); }

    }

Для того, щоб зареєструвати підписника подій, використайте метод addEventSubscriber():

1
2
3
4
5
6
7
8
9
10
11
12
13
use App\Form\EventListener\AddEmailFieldListener;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\TextType;

// ...

$form = $formFactory->createBuilder()
    ->add('username', TextType::class)
    ->add('showEmail', CheckboxType::class)
    ->addEventSubscriber(new AddEmailFieldListener())
    ->getForm();

// ...