Події форми

Дата оновлення перекладу 2022-11-01

Події форми

Компонент Форми надає структурований прроцес, щоб дозволити вам налаштувати ваші форми, використовуючи компонент 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) {
    // ...
};

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

// ...

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

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(). Вона може бути використана для:

  • Зміни даних, наданих під час попередньго заповнення;
  • Зміни форми, в залежності від даних попереднього заповнення (динамічне додавання або видалення полів).
??? ????? ????????
???????? ????. null
????????????? ????. null
???? ????????? null

See also

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

Caution

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

Тип форми 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(). Ця подія в основному призначеня для читання даних після попереднього заповнення форми.

??? ????? ????????
???????? ????. ??????????? ???????? ????
????????????? ????. ???????? ????, ??????????? ?? ????????? ?????????? ?????????????
???? ?????????. ????????????? ????, ??????????? ?? ????????? ????????????? ?????????

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

See also

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

Caution

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

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

C) Подія FormEvents::POST_SUBMIT

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

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

??? ?????. ????????
???????? ???? ????????????? ???? ???????? ??????????? ?? ????????? ????????????? ??????
????????????? ???? ???? ?, ?? ? FormEvents::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_bind FormEvents::PRE_SUBMIT ???? ??????
form.bind FormEvents::SUBMIT ????????????? ????
form.post_bind 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\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;

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

        if (!$user) {
            return;
        }

        // Перевіряє, чи обрав користувач відображати його електронну пошту.
        // Якщо дані були відправлені раніше, додаткове значення, включене
        // у змінних запиту, повинно бути видалене.
        if (true === $user['show_email']) {
            $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\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;

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

    public function onPreSetData(FormEvent $event)
    {
        // ...
    }
}

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

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

  • Покращення читаності;
  • Прослуховування декількох подій;
  • Регрупування декількох слухачів всередині одного класу.
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// src/Form/EventListener/AddEmailFieldListener.php
namespace App\Form\EventListener;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;

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

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

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

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

        if (!$user) {
            return;
        }

        // Перевіряє, чи обрав користувач відображати свою електронну пошту.
        // Якщо дані були відправлені раніше, додаткове значення, включене
        // у змінних запиту, має бути видалене.
        if (true === $user['show_email']) {
            $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\TextType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;

// ...

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

// ...