Form Events

The Form component provides a structured process to let you customize your forms, by making use of the EventDispatcher component. Using form events, you may modify information or fields at different steps of the workflow: from the population of the form to the submission of the data from the request.

フォーム コンポーネントは、EventDispatcher コンポーネントを利用して、フォームをカスタマイズできる構造化されたプロセスを提供します。フォーム イベントを使用すると、ワークフローのさまざまなステップで情報やフィールドを変更できます。フォームへの入力からリクエストからのデータの送信までです。 .

For example, if you need to add a field depending on request values, you can register an event listener to the FormEvents::PRE_SUBMIT event as follows:

たとえば、リクエストの値に応じてフィールドを追加する必要がある場合は、次のように 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) {
    // ...
};

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

// ...

The Form Workflow

1) Pre-populating the Form (FormEvents::PRE_SET_DATA and FormEvents::POST_SET_DATA)

Two events are dispatched during pre-population of a form, when Form::setData() is called: FormEvents::PRE_SET_DATA and FormEvents::POST_SET_DATA.

Form::setData() が呼び出されると、フォームの事前入力中に FormEvents::PRE_SET_DATA と FormEvents::POST_SET_DATA の 2 つのイベントがディスパッチされます。

A) The FormEvents::PRE_SET_DATA Event

The FormEvents::PRE_SET_DATA event is dispatched at the beginning of the Form::setData() method. It can be used to:

FormEvents::PRE_SET_DATA イベントは、Form::setData() メソッドの開始時に送出されます。次の用途に使用できます。
  • Modify the data given during pre-population;
    事前入力中に指定されたデータを変更します。
  • Modify a form depending on the pre-populated data (adding or removing fields dynamically).
    事前入力されたデータに応じてフォームを変更します (フィールドを動的に追加または削除します)。
Data Type Value
Model data null
Normalized data null
View data null

See also

こちらもご覧ください

See all form events at a glance in the Form Events Information Table.

フォーム イベント情報テーブルで、すべてのフォーム イベントを一目で確認できます。

Caution

注意

During FormEvents::PRE_SET_DATA, Form::setData() is locked and will throw an exception if used. If you wish to modify data, you should use FormEvent::setData() instead.

FormEvents::PRE_SET_DATA の間、Form::setData() はロックされ、使用すると例外がスローされます。データを変更したい場合は、代わりに FormEvent::setData() を使用する必要があります。
Form コンポーネントの FormEvents::PRE_SET_DATA

The Symfony\Component\Form\Extension\Core\Type\CollectionType form type relies on the Symfony\Component\Form\Extension\Core\EventListener\ResizeFormListener subscriber, listening to the FormEvents::PRE_SET_DATA event in order to reorder the form's fields depending on the data from the pre-populated object, by removing and adding all form rows.

Symfony\Component\Form\Extension\Core\Type\CollectionType フォーム タイプは、Symfony\Component\Form\Extension\Core\EventListener\ResizeFormListenersubscriber に依存し、データに応じてフォームのフィールドを並べ替えるために FormEvents::PRE_SET_DATA イベントをリッスンします。すべてのフォーム行を削除および追加することにより、事前入力されたオブジェクトから。

B) The FormEvents::POST_SET_DATA Event

The FormEvents::POST_SET_DATA event is dispatched at the end of the Form::setData() method. This event is mostly here for reading data after having pre-populated the form.

FormEvents::POST_SET_DATA イベントは、Form::setData() メソッドの最後にディスパッチされます。このイベントは主に、フォームに事前入力された後にデータを読み取るために使用されます。
Data Type Value
Model data Model data injected into setData()
Normalized data Model data transformed using a model transformer
View data Normalized data transformed using a view transformer

See also

こちらもご覧ください

See all form events at a glance in the Form Events Information Table.

フォーム イベント情報テーブルで、すべてのフォーム イベントを一目で確認できます。
フォーム コンポーネントの FormEvents::POST_SET_DATA

The Symfony\Component\Form\Extension\DataCollector\EventListener\DataCollectorListener class is subscribed to listen to the FormEvents::POST_SET_DATA event in order to collect information about the forms from the denormalized model and view data.

Symfony\Component\Form\Extension\DataCollector\EventListener\DataCollectorListener クラスは、非正規化モデルからフォームに関する情報を収集し、データを表示するために、FormEvents::POST_SET_DATA イベントをリッスンするためにサブスクライブされます。

2) Submitting a Form (FormEvents::PRE_SUBMIT, FormEvents::SUBMIT and FormEvents::POST_SUBMIT)

Three events are dispatched when Form::handleRequest() or Form::submit() are called: FormEvents::PRE_SUBMIT, FormEvents::SUBMIT, FormEvents::POST_SUBMIT.

Form::handleRequest() または Form::submit() が呼び出されると、FormEvents::PRE_SUBMIT、FormEvents::SUBMIT、FormEvents::POST_SUBMIT の 3 つのイベントがディスパッチされます。

A) The FormEvents::PRE_SUBMIT Event

The FormEvents::PRE_SUBMIT event is dispatched at the beginning of the Form::submit() method.

FormEvents::PRE_SUBMIT イベントは、Form::submit() メソッドの開始時にディスパッチされます。

It can be used to:

次の用途に使用できます。
  • Change data from the request, before submitting the data to the form;
    データをフォームに送信する前に、リクエストからデータを変更します。
  • Add or remove form fields, before submitting the data to the form.
    フォームにデータを送信する前に、フォーム フィールドを追加または削除します。
Data Type Value
Model data Same as in FormEvents::POST_SET_DATA
Normalized data Same as in FormEvents::POST_SET_DATA
View data Same as in FormEvents::POST_SET_DATA

See also

こちらもご覧ください

See all form events at a glance in the Form Events Information Table.

フォーム イベント情報テーブルで、すべてのフォーム イベントを一目で確認できます。
Form コンポーネントの FormEvents::PRE_SUBMIT

The Symfony\Component\Form\Extension\Core\EventListener\TrimListener subscriber subscribes to the FormEvents::PRE_SUBMIT event in order to trim the request's data (for string values). The Symfony\Component\Form\Extension\Csrf\EventListener\CsrfValidationListener subscriber subscribes to the FormEvents::PRE_SUBMIT event in order to validate the CSRF token.

Symfony\Component\Form\Extension\Core\EventListener\TrimListenersubscriber は、リクエストのデータ (文字列値) をトリムするために FormEvents::PRE_SUBMIT イベントを購読します。Symfony\Component\Form\Extension\Csrf\EventListener\CsrfValidationListenersubscriber はCSRF トークンを検証するための FormEvents::PRE_SUBMIT イベント。

B) The FormEvents::SUBMIT Event

The FormEvents::SUBMIT event is dispatched right before the Form::submit() method transforms back the normalized data to the model and view data.

FormEvents::SUBMIT イベントは、Form::submit() メソッドが正規化されたデータをモデルおよびビュー データに戻す直前にディスパッチされます。

It can be used to change data from the normalized representation of the data.

データの正規化された表現からデータを変更するために使用できます。
Data Type Value
Model data Same as in FormEvents::POST_SET_DATA
Normalized data Data from the request reverse-transformed from the request using a view transformer
View data Same as in FormEvents::POST_SET_DATA

See also

こちらもご覧ください

See all form events at a glance in the Form Events Information Table.

フォーム イベント情報テーブルで、すべてのフォーム イベントを一目で確認できます。

Caution

注意

At this point, you cannot add or remove fields to the form.

この時点で、フォームにフィールドを追加または削除することはできません。
Form コンポーネントの FormEvents::SUBMIT

The Symfony\Component\Form\Extension\Core\EventListener\FixUrlProtocolListener subscribes to the FormEvents::SUBMIT event in order to prepend a default protocol to URL fields that were submitted without a protocol.

Symfony\Component\Form\Extension\Core\EventListener\FixUrlProtocolListener は、プロトコルなしで送信された URL フィールドに defaultprotocol を追加するために FormEvents::SUBMIT イベントをサブスクライブします。

C) The FormEvents::POST_SUBMIT Event

The FormEvents::POST_SUBMIT event is dispatched after the Form::submit() once the model and view data have been denormalized.

FormEvents::POST_SUBMIT イベントは、モデルとビュー データが非正規化されると、Form::submit() の後にディスパッチされます。

It can be used to fetch data after denormalization.

非正規化後にデータをフェッチするために使用できます。
Data Type Value
Model data Normalized data reverse-transformed using a model transformer
Normalized data Same as in FormEvents::SUBMIT
View data Normalized data transformed using a view transformer

See also

こちらもご覧ください

See all form events at a glance in the Form Events Information Table.

フォーム イベント情報テーブルで、すべてのフォーム イベントを一目で確認できます。

Caution

注意

At this point, you cannot add or remove fields to the current form and its children.

この時点で、現在のフォームとその子にフィールドを追加または削除することはできません。
Form コンポーネントの FormEvents::POST_SUBMIT

The Symfony\Component\Form\Extension\DataCollector\EventListener\DataCollectorListener subscribes to the FormEvents::POST_SUBMIT event in order to collect information about the forms. The Symfony\Component\Form\Extension\Validator\EventListener\ValidationListener subscribes to the FormEvents::POST_SUBMIT event in order to automatically validate the denormalized object.

Symfony\Component\Form\Extension\DataCollector\EventListener\DataCollectorListener は、フォームに関する情報を収集するために FormEvents::POST_SUBMIT イベントをサブスクライブします。非正規化されたオブジェクトを自動的に検証するため。

Registering Event Listeners or Event Subscribers

In order to be able to use Form events, you need to create an event listener or an event subscriber and register it to an event.

フォーム イベントを使用できるようにするには、イベント リスナーまたはイベント サブスクライバーを作成し、イベントに登録する必要があります。

The name of each of the "form" events is defined as a constant on the FormEvents class. Additionally, each event callback (listener or subscriber method) is passed a single argument, which is an instance of FormEvent. The event object contains a reference to the current state of the form and the current data being processed.

各「フォーム」イベントの名前は、FormEvents クラスの定数として定義されます。さらに、各イベント コールバック (リスナーまたはサブスクライバー メソッド) は、FormEvent のインスタンスである単一の引数として渡されます。イベント オブジェクトには、フォームの現在の状態と処理中の現在のデータへの参照が含まれています。
Name FormEvents Constant Event's Data
form.pre_set_data FormEvents::PRE_SET_DATA Model data
form.post_set_data FormEvents::POST_SET_DATA Model data
form.pre_submit FormEvents::PRE_SUBMIT Request data
form.submit FormEvents::SUBMIT Normalized data
form.post_submit FormEvents::POST_SUBMIT View data

Event Listeners

An event listener may be any type of valid callable. For example, you can define an event listener function inline right in the addEventListener method of the FormFactory:

イベント リスナーは、有効な callable の任意の型である可能性があります。たとえば、FormFactory の addEventListener メソッドでイベント リスナー関数をインラインで定義できます。
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\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;

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

        if (!$user) {
            return;
        }

        // checks whether the user has chosen to display their email or not.
        // If the data was submitted previously, the additional value that is
        // included in the request variables needs to be removed.
        if (isset($user['showEmail']) && $user['showEmail']) {
            $form->add('email', EmailType::class);
        } else {
            unset($user['email']);
            $event->setData($user);
        }
    })
    ->getForm();

// ...

When you have created a form type class, you can use one of its methods as a callback for better readability:

フォーム タイプ クラスを作成したら、読みやすくするために、そのメソッドの 1 つをコールバックとして使用できます。
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\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormEvent;
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(FormEvent $event): void
    {
        // ...
    }
}

Event Subscribers

Event subscribers have different uses:

イベント サブスクライバーにはさまざまな用途があります。
  • Improving readability;
    読みやすさの向上;
  • Listening to multiple events;
    複数のイベントを聞く;
  • Regrouping multiple listeners inside a single class.
    単一のクラス内で複数のリスナーを再グループ化します。

Consider the following example of a form event subscriber:

次のフォーム イベント サブスクライバーの例を考えてみましょう。
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): void
    {
        $user = $event->getData();
        $form = $event->getForm();

        // checks whether the user from the initial data has chosen to
        // display their email or not.
        if (true === $user->isShowEmail()) {
            $form->add('email', EmailType::class);
        }
    }

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

        if (!$user) {
            return;
        }

        // checks whether the user has chosen to display their email or not.
        // If the data was submitted previously, the additional value that
        // is included in the request variables needs to be removed.
        if (isset($user['showEmail']) && $user['showEmail']) {
            $form->add('email', EmailType::class);
        } else {
            unset($user['email']);
            $event->setData($user);
        }
    }
}

To register the event subscriber, use the addEventSubscriber() method:

イベント サブスクライバーを登録するには、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();

// ...