События формы
Дата обновления перевода 2024-07-19
События формы
Компонент Form предоставляет структурированный процесс, чтобы позволить вам настроить ваши формы, используя компонент EventDispatcher. Используя события формы, вы можете изменять информацию или поля на разных этапах рабочего процесса: от наполнения формы до отправки данных из запроса.
Например, если вы хотите зарегистрировать функцию в событии
FormEvents::PRE_SUBMIT
, следующий код позволяет вам добавить поле,
в зависимости от значений запроса:
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()
// ... добавить поля формы
->addEventListener(FormEvents::PRE_SUBMIT, $listener);
// ...
Рабочий процесс формы
В жизненном цикле формы есть два момента, когда данные формы могут быть обновлены:
- Во время предварительного заполнения (
setData()
) при создании формы; - При обработке отправки формы (
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
Увидеть все события форм одномоментно вы можете в Информационной таблице о событиях форм .
B) Событие FormEvents::POST_SET_DATA
Событие FormEvents::POST_SET_DATA
развёртывается в конце метода
Form::setData(). Это
событие может быть использовано для изменения формы, в зависимости от
заполненных данных (динамическое добавление или удаление полей).
??? ?????? | ???????? |
---|---|
?????? ??????? | ????????? ??????, ?????????? ? setData() |
????????? ?????? | ????????? ??????, ?????????? ? setData() |
??????????????? ?????? | ????????? ??????, ??????????????? ? ??????? ?????????? ??????????????? |
?????? ????????? | ??????????????? ??????, ??????????????? ? ??????? ??????????????? ????????? |
See also
Увидеть все события форм одномоментно вы можете в Информационной таблице о событиях форм .
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
Увидеть все события форм одномоментно вы можете в Информационной таблице о событиях форм .
B) Событие FormEvents::SUBMIT
Событие FormEvents::SUBMIT
развёртывается прямо перед тем, как метод
Form::submit() преобразует
нормализированные данные в модельные данные и данные просмотра.
Оно может быть использовано для изменения данных из нормализированного представления данных.
??? ?????? | ???????? |
---|---|
?????? ??????? | ?????? ?? ???????, ??????????????? ??????? ?? ??????? ? ?????????????? ??????????????? ????????? |
????????? ?????? | ????? ??, ??? ? FormEvents::POST_SET_DATA |
??????????????? ?????? | ????? ??, ??? ? FormEvents::POST_SET_DATA |
?????? ????????? | ????? ??, ??? ? FormEvents::POST_SET_DATA |
See also
Увидеть все события форм одномоментно вы можете в Информационной таблице о событиях форм .
Caution
На этом этапе вы не можете добавлять или удалять поля из формы.
C) Событие FormEvents::POST_SUBMIT
Событие FormEvents::POST_SUBMIT
развёртывается после
Form::submit(), когда
были денормализированы модельные данные и данные просмотра.
Оно может быть использовано, чтобы извлекать данные после денормализации.
??? ?????? | ???????? |
---|---|
?????? ??????? | ??????????????? ??????, ??????????????? ? ??????? ??????????????? ????????? |
????????? ?????? | ??????????????? ??????, ??????????????? ??????? ? ??????? ??????????????? ?????? |
??????????????? ?????? | ?????? ?? ???????, ??????????????? ??????? ?? ??????? ? ??????? ??????????????? ????????? |
?????? ????????? | ??????????????? ?????? ??????????????? ? ??????? ??????????????? ????????? |
See also
Увидеть все события форм одномоментно вы можете в Информационной таблице о событиях форм .
Caution
На этом этапе вы не можете добавлять или удалять поля из формы.
Регистрация слушателей или подписчиков событий
Для того, чтобы иметь возможность использовать события формы, вам нужно создать слушателя или подписчика событий и зарегистрировать его в событии.
Имя каждого события "формы" определяется как константа в классе 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\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
{
// ...
}
}
Подписчики событий
Подписчики событий имеют разные применения:
- Улучшение читаемости;
- Прослушивание нескольких событий;
- Регруппировка нескольких слушателей внутри одного класса.
Рассмотрим следующий пример подписчика событий формы:
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 51
// src/Form/EventListener/AddEmailFieldListener.php
namespace App\Form\EventListener;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\Event\PreSetDataEvent;
use Symfony\Component\Form\Event\PreSubmitEvent;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
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(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();
// ...