Forms

Screencast

スクリーンキャスト

Do you prefer video tutorials? Check out the Symfony Forms screencast series.

ビデオチュートリアルが好きですか? Symfony Forms スクリーンキャスト シリーズをチェックしてください。

Creating and processing HTML forms is hard and repetitive. You need to deal with rendering HTML form fields, validating submitted data, mapping the form data into objects and a lot more. Symfony includes a powerful form feature that provides all these features and many more for truly complex scenarios.

HTML フォームの作成と処理は困難で反復的です。 HTML フォーム フィールドのレンダリング、送信されたデータの検証、フォーム データのオブジェクトへのマッピングなどを処理する必要があります。 Symfony には、これらすべての機能を提供する強力なフォーム機能が含まれており、真に複雑なシナリオのためにさらに多くの機能を提供します。

Installation

In applications using Symfony Flex, run this command to install the form feature before using it:

Symfony Flex を使用するアプリケーションでは、次のコマンドを実行して、使用する前にフォーム機能をインストールします。
1
$ composer require symfony/form

Usage

The recommended workflow when working with Symfony forms is the following:

Symfony フォームを操作する際の推奨ワークフローは次のとおりです。
  1. Build the form in a Symfony controller or using a dedicated form class;
    Symfony コントローラまたは専用のフォーム クラスを使用してフォームを構築します。
  2. Render the form in a template so the user can edit and submit it;
    ユーザーが編集して送信できるように、テンプレートでフォームをレンダリングします。
  3. Process the form to validate the submitted data, transform it into PHP data and do something with it (e.g. persist it in a database).
    フォームを処理して送信されたデータを検証し、それを PHPdata に変換して、何かを行います (データベースに保存するなど)。

Each of these steps is explained in detail in the next sections. To make examples easier to follow, all of them assume that you're building a small Todo list application that displays "tasks".

これらの各手順については、次のセクションで詳しく説明します。例を理解しやすくするために、これらの例はすべて、「タスク」を表示する小さな Todolist アプリケーションを作成していることを前提としています。

Users create and edit tasks using Symfony forms. Each task is an instance of the following Task class:

ユーザーは、Symfony フォームを使用してタスクを作成および編集します。各タスクは、次の Task クラスのインスタンスです。
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/Entity/Task.php
namespace App\Entity;

class Task
{
    protected $task;
    protected $dueDate;

    public function getTask(): string
    {
        return $this->task;
    }

    public function setTask(string $task): void
    {
        $this->task = $task;
    }

    public function getDueDate(): ?\DateTime
    {
        return $this->dueDate;
    }

    public function setDueDate(?\DateTime $dueDate): void
    {
        $this->dueDate = $dueDate;
    }
}

This class is a "plain-old-PHP-object" because, so far, it has nothing to do with Symfony or any other library. It's a normal PHP object that directly solves a problem inside your application (i.e. the need to represent a task in your application). But you can also edit Doctrine entities in the same way.

これまでのところ、Symfony やその他のライブラリとは何の関係もないため、このクラスは「昔ながらの PHP オブジェクト」です。これは、アプリケーション内の問題 (つまり、アプリケーションでタスクを表す必要性) を直接解決する通常の PHP オブジェクトです。しかし、同じ方法で Doctrine エンティティを編集することもできます。

Form Types

Before creating your first Symfony form, it's important to understand the concept of "form type". In other projects, it's common to differentiate between "forms" and "form fields". In Symfony, all of them are "form types":

最初の Symfony フォームを作成する前に、「フォーム タイプ」の概念を理解することが重要です。他のプロジェクトでは、「フォーム」と「フォーム フィールド」を区別するのが一般的です。 Symfony では、それらはすべて「フォーム タイプ」です。
  • a single <input type="text"> form field is a "form type" (e.g. TextType);
    singleform フィールドは「フォーム タイプ」です (例: TextType)。
  • a group of several HTML fields used to input a postal address is a "form type" (e.g. PostalAddressType);
    住所を入力するために使用されるいくつかの HTML フィールドのグループは、「フォーム タイプ」です (例: PostalAddressType)。
  • an entire <form> with multiple fields to edit a user profile is a "form type" (e.g. UserProfileType).
    ユーザープロファイルを編集するための複数のフィールドを持つ全体が「フォームタイプ」です (例: UserProfileType)。

This may be confusing at first, but it will feel natural to you soon enough. Besides, it simplifies code and makes "composing" and "embedding" form fields much easier to implement.

これは最初は戸惑うかもしれませんが、すぐに自然に感じるようになります。また、コードが単純になり、フォーム フィールドの「作成」と「埋め込み」がはるかに簡単に実装できるようになります。

There are tens of form types provided by Symfony and you can also create your own form types.

Symfony が提供する数十のフォーム タイプがあり、独自のフォーム タイプを作成することもできます。

Building Forms

Symfony provides a "form builder" object which allows you to describe the form fields using a fluent interface. Later, this builder creates the actual form object used to render and process contents.

Symfony は、流暢なインターフェースを使用してフォームフィールドを記述できる「フォームビルダー」オブジェクトを提供します。後で、このビルダーは、コンテンツのレンダリングと処理に使用される実際のフォーム オブジェクトを作成します。

Creating Forms in Controllers

If your controller extends from the AbstractController, use the createFormBuilder() helper:

コントローラーが AbstractController から拡張されている場合は、createFormBuilder() ヘルパーを使用します。
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
// src/Controller/TaskController.php
namespace App\Controller;

use App\Entity\Task;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class TaskController extends AbstractController
{
    public function new(Request $request): Response
    {
        // creates a task object and initializes some data for this example
        $task = new Task();
        $task->setTask('Write a blog post');
        $task->setDueDate(new \DateTime('tomorrow'));

        $form = $this->createFormBuilder($task)
            ->add('task', TextType::class)
            ->add('dueDate', DateType::class)
            ->add('save', SubmitType::class, ['label' => 'Create Task'])
            ->getForm();

        // ...
    }
}

If your controller does not extend from AbstractController, you'll need to fetch services in your controller and use the createBuilder() method of the form.factory service.

コントローラーが AbstractController から拡張されていない場合は、コントローラーでサービスをフェッチし、form.factory サービスの createBuilder() メソッドを使用する必要があります。

In this example, you've added two fields to your form - task and dueDate - corresponding to the task and dueDate properties of the Task class. You've also assigned each a form type (e.g. TextType and DateType), represented by its fully qualified class name. Finally, you added a submit button with a custom label for submitting the form to the server.

この例では、Taskclass の task および dueDate プロパティに対応する task および dueDate という 2 つのフィールドをフォームに追加しました。また、それぞれに完全修飾クラス名で表されるフォーム タイプ (TextType や DateType など) を割り当てました。最後に、フォームをサーバーに送信するためのカスタム ラベル付きの送信ボタンを追加しました。

Creating Form Classes

Symfony recommends putting as little logic as possible in controllers. That's why it's better to move complex forms to dedicated classes instead of defining them in controller actions. Besides, forms defined in classes can be reused in multiple actions and services.

symfony は、コントローラーに入れるロジックをできるだけ少なくすることを推奨しています。そのため、min コントローラー アクションを定義する代わりに、複雑なフォームを専用のクラスに移動することをお勧めします。また、クラスで定義されたフォームは、複数のアクションやサービスで再利用できます。

Form classes are form types that implement FormTypeInterface. However, it's better to extend from AbstractType, which already implements the interface and provides some utilities:

フォーム クラスは、FormTypeInterface を実装するフォーム タイプです。ただし、既にインターフェイスを実装し、いくつかのユーティリティを提供する AbstractType から拡張することをお勧めします。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// src/Form/Type/TaskType.php
namespace App\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;

class TaskType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('task', TextType::class)
            ->add('dueDate', DateType::class)
            ->add('save', SubmitType::class)
        ;
    }
}

Tip

ヒント

Install the MakerBundle in your project to generate form classes using the make:form and make:registration-form commands.

プロジェクトに MakerBundle をインストールして、make:form および make:registration-form コマンドを使用してフォーム クラスを生成します。

The form class contains all the directions needed to create the task form. In controllers extending from the AbstractController, use the createForm() helper (otherwise, use the create() method of the form.factory service):

フォーム クラスには、タスク フォームを作成するために必要なすべての指示が含まれています。 AbstractController から拡張されたコントローラーでは、createForm() ヘルパーを使用します (それ以外の場合は、form.factory サービスの create() メソッドを使用します)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// src/Controller/TaskController.php
namespace App\Controller;

use App\Form\Type\TaskType;
// ...

class TaskController extends AbstractController
{
    public function new(): Response
    {
        // creates a task object and initializes some data for this example
        $task = new Task();
        $task->setTask('Write a blog post');
        $task->setDueDate(new \DateTime('tomorrow'));

        $form = $this->createForm(TaskType::class, $task);

        // ...
    }
}

Every form needs to know the name of the class that holds the underlying data (e.g. App\Entity\Task). Usually, this is just guessed based off of the object passed to the second argument to createForm() (i.e. $task). Later, when you begin embedding forms, this will no longer be sufficient.

すべてのフォームは、基になるデータを保持するクラスの名前を知る必要があります (例: App\Entity\Task)。通常、これは createForm() の 2 番目の引数 (つまり $task) に渡されたオブジェクトに基づいて推測されます。後でフォームの埋め込みを開始すると、これでは十分ではなくなります。

So, while not always necessary, it's generally a good idea to explicitly specify the data_class option by adding the following to your form type class:

そのため、常に必要というわけではありませんが、フォーム タイプ クラスに次のコードを追加して、data_class オプションを明示的に指定することをお勧めします。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// src/Form/Type/TaskType.php
namespace App\Form\Type;

use App\Entity\Task;
use Symfony\Component\OptionsResolver\OptionsResolver;
// ...

class TaskType extends AbstractType
{
    // ...

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'data_class' => Task::class,
        ]);
    }
}

Rendering Forms

Now that the form has been created, the next step is to render it:

フォームが作成されたので、次のステップはそれをレンダリングすることです。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// src/Controller/TaskController.php
namespace App\Controller;

use App\Entity\Task;
use App\Form\Type\TaskType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class TaskController extends AbstractController
{
    public function new(Request $request): Response
    {
        $task = new Task();
        // ...

        $form = $this->createForm(TaskType::class, $task);

        return $this->render('task/new.html.twig', [
            'form' => $form,
        ]);
    }
}

Internally, the render() method calls $form->createView() to transform the form into a form view instance.

内部的には、render() メソッドは $form->createView() を呼び出して、フォームをフォーム ビュー インスタンスに変換します。

6.2

6.2

Prior to Symfony 6.2, you had to use $this->render(..., ['form' => $form->createView()]) or the renderForm() method to render to form. The renderForm() method is deprecated in favor of directly passing the FormInterface instance to render().

Symfony 6.2 より前は、$this->render(..., ['form' => $form->createView()]) または renderForm() メソッドを使用してフォームにレンダリングする必要がありました。 renderForm() メソッドは廃止され、FormInterface インスタンスを render() に直接渡すことが推奨されています。

Then, use some form helper functions to render the form contents:

次に、いくつかのフォーム ヘルパー関数を使用して、フォームの内容を変換します。
1
2
{# templates/task/new.html.twig #}
{{ form(form) }}

That's it! The form() function renders all fields and the <form> start and end tags. By default, the form method is POST and the target URL is the same that displayed the form, but you can change both.

それでおしまい! form() 関数は、すべてのフィールドと開始タグと終了タグをレンダリングします。デフォルトでは、フォーム メソッドは POST で、ターゲット URL はフォームを表示したものと同じですが、両方を変更できます。

Notice how the rendered task input field has the value of the task property from the $task object (i.e. "Write a blog post"). This is the first job of a form: to take data from an object and translate it into a format that's suitable for being rendered in an HTML form.

レンダリングされたタスク入力フィールドが $task オブジェクトからの taskproperty の値を持っていることに注意してください (つまり、「ブログ投稿を書く」)。オブジェクトからデータを取得し、HTML フォームでのレンダリングに適した形式に変換することは、フォームの最初の仕事です。

Tip

ヒント

The form system is smart enough to access the value of the protected task property via the getTask() and setTask() methods on the Task class. Unless a property is public, it must have a "getter" and "setter" method so that Symfony can get and put data onto the property. For a boolean property, you can use an "isser" or "hasser" method (e.g. isPublished() or hasReminder()) instead of a getter (e.g. getPublished() or getReminder()).

フォーム システムは、theTask クラスの getTask() および setTask() メソッドを介して protectedtask プロパティの値にアクセスできるほどスマートです。プロパティがパブリックでない限り、Symfony がデータを取得してプロパティに配置できるように、「getter」および「setter」メソッドが必要です。ブール型プロパティの場合、ゲッター (getPublished() または getReminder() など) の代わりに「isser」または「hasser」メソッド (isPublished() または hasReminder() など) を使用できます。

As short as this rendering is, it's not very flexible. Usually, you'll need more control about how the entire form or some of its fields look. For example, thanks to the Bootstrap 5 integration with Symfony forms you can set this option to generate forms compatible with the Bootstrap 5 CSS framework:

このレンダリングは短いので、あまり柔軟ではありません。通常、フォーム全体または一部のフィールドの外観をより詳細に制御する必要があります。たとえば、Symfony フォームとの Bootstrap 5 統合のおかげで、このオプションを設定して、Bootstrap 5 CSS フレームワークと互換性のあるフォームを生成できます。
  • YAML
    YAML
  • XML
    XML
  • PHP
    PHP
1
2
3
# config/packages/twig.yaml
twig:
    form_themes: ['bootstrap_5_layout.html.twig']

The built-in Symfony form themes include Bootstrap 3, 4 and 5, Foundation 5 and 6, as well as Tailwind 2. You can also create your own Symfony form theme.

組み込みの Symfony フォーム テーマには、Bootstrap 3、4、5、Foundation 5、6、および Tailwind 2 が含まれます。独自の Symfony フォーム テーマを作成することもできます。

In addition to form themes, Symfony allows you to customize the way fields are rendered with multiple functions to render each field part separately (widgets, labels, errors, help messages, etc.)

フォーム テーマに加えて、Symfony では、各フィールド パーツ (ウィジェット、ラベル、エラー、ヘルプ メッセージなど) を個別にレンダリングする複数の関数を使用して、フィールドのレンダリング方法をカスタマイズできます。

Processing Forms

The recommended way of processing forms is to use a single action for both rendering the form and handling the form submit. You can use separate actions, but using one action simplifies everything while keeping the code concise and maintainable.

フォームを処理する推奨される方法は、フォームのレンダリングとフォーム送信の処理の両方に単一のアクションを使用することです。別々のアクションを使用できますが、1 つのアクションを使用すると、コードを簡潔で保守しやすく保ちながら、すべてが簡素化されます。

Processing a form means to translate user-submitted data back to the properties of an object. To make this happen, the submitted data from the user must be written into the form object:

フォームの処理とは、ユーザーが送信したデータをオブジェクトのプロパティに変換することを意味します。これを実現するには、ユーザーから送信されたデータをフォーム オブジェクトに書き込む必要があります。
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
// src/Controller/TaskController.php

// ...
use Symfony\Component\HttpFoundation\Request;

class TaskController extends AbstractController
{
    public function new(Request $request): Response
    {
        // just set up a fresh $task object (remove the example data)
        $task = new Task();

        $form = $this->createForm(TaskType::class, $task);

        $form->handleRequest($request);
        if ($form->isSubmitted() && $form->isValid()) {
            // $form->getData() holds the submitted values
            // but, the original `$task` variable has also been updated
            $task = $form->getData();

            // ... perform some action, such as saving the task to the database

            return $this->redirectToRoute('task_success');
        }

        return $this->render('task/new.html.twig', [
            'form' => $form,
        ]);
    }
}

This controller follows a common pattern for handling forms and has three possible paths:

このコントローラーは、フォームを処理するための一般的なパターンに従い、3 つの可能なパスがあります。
  1. When initially loading the page in a browser, the form hasn't been submitted yet and $form->isSubmitted() returns false. So, the form is created and rendered;
    ブラウザーで最初にページをロードするとき、フォームはまだ送信されておらず、$form->isSubmitted() は false を返します。したがって、フォームが作成されてレンダリングされます。
  2. When the user submits the form, handleRequest() recognizes this and immediately writes the submitted data back into the task and dueDate properties of the $task object. Then this object is validated (validation is explained in the next section). If it is invalid, isValid() returns false and the form is rendered again, but now with validation errors.

    ユーザーがフォームを送信すると、handleRequest() はこれを認識し、送信されたデータをすぐに $task オブジェクトの task および dueDate プロパティに書き込みます。次に、このオブジェクトが検証されます (検証については、次のセクションで説明します)。無効な場合、isValid() は false を返し、フォームが再度レンダリングされますが、検証エラーが発生します。

    By passing $form to the render() method (instead of $form->createView()), the response code is automatically set to HTTP 422 Unprocessable Content. This ensures compatibility with tools relying on the HTTP specification, like Symfony UX Turbo;

    $form を ($form->createView() の代わりに) render() メソッドに渡すと、応答コードは自動的に HTTP 422 Unprocessable Content に設定されます。これにより、Symfony UX Turbo などの HTTP 仕様に依存するツールとの互換性が確保されます。
  3. When the user submits the form with valid data, the submitted data is again written into the form, but this time isValid() returns true. Now you have the opportunity to perform some actions using the $task object (e.g. persisting it to the database) before redirecting the user to some other page (e.g. a "thank you" or "success" page);
    ユーザーが有効なデータを含むフォームを送信すると、送信されたデータが再度フォームに書き込まれますが、今回は isValid() が true を返します。これで、ユーザーを別のページ (「ありがとう」や「成功」ページなど) にリダイレクトする前に、$task オブジェクトを使用していくつかのアクション (データベースへの永続化など) を実行する機会が得られます。

Note

ノート

Redirecting a user after a successful form submission is a best practice that prevents the user from being able to hit the "Refresh" button of their browser and re-post the data.

フォームの送信が成功した後にユーザーをリダイレクトすることは、ユーザーがブラウザーの [更新] ボタンを押してデータを再投稿できないようにするためのベスト プラクティスです。

See also

こちらもご覧ください

If you need more control over exactly when your form is submitted or which data is passed to it, you can use the submit() method to handle form submissions.

フォームがいつ送信されるか、またはフォームに渡されるデータを正確に制御する必要がある場合は、submit() メソッドを使用してフォームの送信を処理できます。

Validating Forms

In the previous section, you learned how a form can be submitted with valid or invalid data. In Symfony, the question isn't whether the "form" is valid, but whether or not the underlying object ($task in this example) is valid after the form has applied the submitted data to it. Calling $form->isValid() is a shortcut that asks the $task object whether or not it has valid data.

前のセクションでは、有効または無効なデータでフォームを送信する方法を学びました。 Symfony では、問題は「フォーム」が有効かどうかではなく、フォームが送信されたデータを適用した後に、基になるオブジェクト (この例では $task) が有効かどうかです。 $form->isValid() の呼び出しは、$task オブジェクトに有効なデータがあるかどうかを尋ねるショートカットです。

Before using validation, add support for it in your application:

検証を使用する前に、アプリケーションに検証のサポートを追加してください。
1
$ composer require symfony/validator

Validation is done by adding a set of rules, called (validation) constraints, to a class. You can add them either to the entity class or to the form class.

検証は、(検証) 制約と呼ばれる一連の規則をクラスに追加することによって行われます。それらは、エンティティ クラスまたはフォーム クラスのいずれかに追加できます。

To see the first approach - adding constraints to the entity - in action, add the validation constraints, so that the task field cannot be empty, and the dueDate field cannot be empty, and must be a valid DateTime object.

最初のアプローチ (エンティティに制約を追加する) の動作を確認するには、検証制約を追加して、タスク フィールドを空にできず、dueDate フィールドを空にできず、有効な DateTime オブジェクトでなければなりません。
  • Attributes
    属性
  • YAML
    YAML
  • XML
    XML
  • PHP
    PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// src/Entity/Task.php
namespace App\Entity;

use Symfony\Component\Validator\Constraints as Assert;

class Task
{
    #[Assert\NotBlank]
    public $task;

    #[Assert\NotBlank]
    #[Assert\Type(\DateTime::class)]
    protected $dueDate;
}

That's it! If you re-submit the form with invalid data, you'll see the corresponding errors printed out with the form.

それでおしまい!無効なデータを含むフォームを再送信すると、対応するエラーがフォームと共に出力されます。

To see the second approach - adding constraints to the form - and to learn more about the validation constraints, please refer to the Symfony validation documentation.

フォームに制約を追加する 2 番目のアプローチを確認し、検証の制約について詳しく知るには、Symfony の検証ドキュメントを参照してください。

Other Common Form Features

Passing Options to Forms

If you create forms in classes, when building the form in the controller you can pass custom options to it as the third optional argument of createForm():

クラスでフォームを作成する場合、コントローラーでフォームを作成するときに、カスタム オプションを createForm() の 3 番目のオプションの引数として渡すことができます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// src/Controller/TaskController.php
namespace App\Controller;

use App\Form\Type\TaskType;
// ...

class TaskController extends AbstractController
{
    public function new(): Response
    {
        $task = new Task();
        // use some PHP logic to decide if this form field is required or not
        $dueDateIsRequired = ...;

        $form = $this->createForm(TaskType::class, $task, [
            'require_due_date' => $dueDateIsRequired,
        ]);

        // ...
    }
}

If you try to use the form now, you'll see an error message: The option "require_due_date" does not exist. That's because forms must declare all the options they accept using the configureOptions() method:

今すぐフォームを使用しようとすると、次のエラー メッセージが表示されます。オプション「require_due_date」が存在しません。これは、フォームが configureOptions() メソッドを使用して受け入れるすべてのオプションを宣言する必要があるためです。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// src/Form/Type/TaskType.php
namespace App\Form\Type;

use Symfony\Component\OptionsResolver\OptionsResolver;
// ...

class TaskType extends AbstractType
{
    // ...

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            // ...,
            'require_due_date' => false,
        ]);

        // you can also define the allowed types, allowed values and
        // any other feature supported by the OptionsResolver component
        $resolver->setAllowedTypes('require_due_date', 'bool');
    }
}

Now you can use this new form option inside the buildForm() method:

buildForm() メソッド内でこの新しいフォーム オプションを使用できるようになりました。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// src/Form/Type/TaskType.php
namespace App\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\FormBuilderInterface;

class TaskType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            // ...
            ->add('dueDate', DateType::class, [
                'required' => $options['require_due_date'],
            ])
        ;
    }

    // ...
}

Form Type Options

Each form type has a number of options to configure it, as explained in the Symfony form types reference. Two commonly used options are required and label.

各フォーム タイプには、Symfony フォーム タイプ リファレンスで説明されているように、それを構成するための多数のオプションがあります。

The required Option

The most common option is the required option, which can be applied to any field. By default, this option is set to true, meaning that HTML5-ready browsers will require you to fill in all fields before submitting the form.

最も一般的なオプションは必須オプションで、任意のフィールドに適用できます。デフォルトでは、このオプションは true に設定されています。つまり、HTML5 対応ブラウザでは、フォームを送信する前にすべてのフィールドに入力する必要があります。

If you don't want this behavior, either disable client-side validation for the entire form or set the required option to false on one or more fields:

この動作を望まない場合は、フォーム全体のクライアント側の検証を無効にするか、1 つ以上のフィールドで必要なオプションを false に設定します。
1
2
3
->add('dueDate', DateType::class, [
    'required' => false,
])

The required option does not perform any server-side validation. If a user submits a blank value for the field (either with an old browser or a web service, for example), it will be accepted as a valid value unless you also use Symfony's NotBlank or NotNull validation constraints.

required オプションは、サーバー側の検証を実行しません。ユーザーがフィールドに空の値を送信した場合 (古いブラウザーや Web サービスなど)、Symfony の NotBlank または NotNull 検証制約も使用しない限り、有効な値として受け入れられます。

The label Option

By default, the label of form fields are the humanized version of the property name (user -> User; postalAddress -> Postal Address). Set the label option on fields to define their labels explicitly:

デフォルトでは、フォーム フィールドのラベルは、プロパティ名の人間化されたバージョンです (user -> User; postalAddress -> Postal Address)。ラベルを明示的に定義するには、フィールドに label オプションを設定します。
1
2
3
4
->add('dueDate', DateType::class, [
    // set it to FALSE to not display the label for this field
    'label' => 'To Be Completed Before',
])

Tip

ヒント

By default, <label> tags of required fields are rendered with a required CSS class, so you can display an asterisk by applying a CSS style:

デフォルトでは、必須フィールドのタグは必須の CSS クラスでレンダリングされるため、CSS スタイルを適用してアスタリスクを表示できます。
1
2
3
label.required:before {
    content: "*";
}

Changing the Action and HTTP Method

By default, a form will be submitted via an HTTP POST request to the same URL under which the form was rendered. When building the form in the controller, use the setAction() and setMethod() methods to change this:

デフォルトでは、フォームは HTTP POST リクエストを介して、フォームがレンダリングされた同じ URL に送信されます。コントローラーでフォームを作成するときは、setAction() および setMethod() メソッドを使用してこれを変更します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// src/Controller/TaskController.php
namespace App\Controller;

// ...
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;

class TaskController extends AbstractController
{
    public function new(): Response
    {
        // ...

        $form = $this->createFormBuilder($task)
            ->setAction($this->generateUrl('target_route'))
            ->setMethod('GET')
            // ...
            ->getForm();

        // ...
    }
}

When building the form in a class, pass the action and method as form options:

クラスでフォームを作成するときは、アクションとメソッドをフォーム オプションとして渡します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// src/Controller/TaskController.php
namespace App\Controller;

use App\Form\TaskType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
// ...

class TaskController extends AbstractController
{
    public function new(): Response
    {
        // ...

        $form = $this->createForm(TaskType::class, $task, [
            'action' => $this->generateUrl('target_route'),
            'method' => 'GET',
        ]);

        // ...
    }
}

Finally, you can override the action and method in the template by passing them to the form() or the form_start() helper functions:

最後に、テンプレートのアクションとメソッドを form() または form_start() ヘルパー関数に渡すことでオーバーライドできます。
1
2
{# templates/task/new.html.twig #}
{{ form_start(form, {'action': path('target_route'), 'method': 'GET'}) }}

Note

ノート

If the form's method is not GET or POST, but PUT, PATCH or DELETE, Symfony will insert a hidden field with the name _method that stores this method. The form will be submitted in a normal POST request, but Symfony's routing is capable of detecting the _method parameter and will interpret it as a PUT, PATCH or DELETE request. The Framework Configuration Reference (FrameworkBundle) option must be enabled for this to work.

フォームのメソッドが GET または POST ではなく、PUT、PATCH、または DELETE である場合、Symfony はこのメソッドを格納する _method という名前の隠しフィールドを挿入します。フォームは通常の POST リクエストで送信されますが、Symfony のルーティングは the_method パラメータを検出でき、それを PUT、PATCH、または DELETE リクエストとして解釈します。これを機能させるには、Framework Configuration Reference (FrameworkBundle) オプションを有効にする必要があります。

Changing the Form Name

If you inspect the HTML contents of the rendered form, you'll see that the <form> name and the field names are generated from the type class name (e.g. <form name="task" ...> and <select name="task[dueDate][date][month]" ...>).

レンダリングされたフォームの HTML コンテンツを調べると、名前とフィールド名が型クラス名 (and など) から生成されていることがわかります。

If you want to modify this, use the createNamed() method:

これを変更する場合は、createNamed() メソッドを使用します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// src/Controller/TaskController.php
namespace App\Controller;

use App\Form\TaskType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\FormFactoryInterface;
// ...

class TaskController extends AbstractController
{
    public function new(FormFactoryInterface $formFactory): Response
    {
        $task = ...;
        $form = $formFactory->createNamed('my_name', TaskType::class, $task);

        // ...
    }
}

You can even suppress the name completely by setting it to an empty string.

名前を空の文字列に設定することで、名前を完全に非表示にすることもできます。

Client-Side HTML Validation

Thanks to HTML5, many browsers can natively enforce certain validation constraints on the client side. The most common validation is activated by adding a required attribute on fields that are required. For browsers that support HTML5, this will result in a native browser message being displayed if the user tries to submit the form with that field blank.

HTML5 のおかげで、多くのブラウザーは、クライアント側で特定の検証制約をネイティブに適用できます。最も一般的な検証は、必須フィールドに必須属性を追加することによってアクティブ化されます。 HTML5 をサポートするブラウザーの場合、ユーザーがそのフィールドを空白にしてフォームを送信しようとすると、ネイティブ ブラウザー メッセージが表示されます。

Generated forms take full advantage of this new feature by adding sensible HTML attributes that trigger the validation. The client-side validation, however, can be disabled by adding the novalidate attribute to the <form> tag or formnovalidate to the submit tag. This is especially useful when you want to test your server-side validation constraints, but are being prevented by your browser from, for example, submitting blank fields.

生成されたフォームは、妥当な HTML 属性を追加して検証をトリガーすることにより、この新機能を最大限に活用します。ただし、クライアント側の検証は、タグに novalidate 属性を追加するか、submit タグに formnovalidate を追加することで無効にすることができます。これは、サーバー側の検証の制約をテストしたいが、たとえば空白のフィールドを送信することがブラウザによって妨げられている場合に特に便利です。
1
2
3
4
{# templates/task/new.html.twig #}
{{ form_start(form, {'attr': {'novalidate': 'novalidate'}}) }}
    {{ form_widget(form) }}
{{ form_end(form) }}

Form Type Guessing

If the object handled by the form includes validation constraints, Symfony can introspect that metadata to guess the type of your field. In the above example, Symfony can guess from the validation rules that the task field is a normal TextType field and the dueDate field is a DateType field.

フォームによって処理されるオブジェクトに検証制約が含まれている場合、Symfony はそのメタデータをイントロスペクトしてフィールドのタイプを推測できます。上記の例では、Symfony は検証ルールから、タスク フィールドが通常の TextType フィールドであり、dueDate フィールドが DateType フィールドであることを推測できます。 .

To enable Symfony's "guessing mechanism", omit the second argument to the add() method, or pass null to it:

Symfony の「推測メカニズム」を有効にするには、add() メソッドの 2 番目の引数を省略するか、null を渡します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// src/Form/Type/TaskType.php
namespace App\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;

class TaskType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            // if you don't define field options, you can omit the second argument
            ->add('task')
            // if you define field options, pass NULL as second argument
            ->add('dueDate', null, ['required' => false])
            ->add('save', SubmitType::class)
        ;
    }
}

Caution

注意

When using a specific form validation group, the field type guesser will still consider all validation constraints when guessing your field types (including constraints that are not part of the validation group(s) being used).

特定のフォーム検証グループを使用する場合、フィールド タイプ ゲッサーは、フィールド タイプを推測するときにすべての検証制約を考慮します (使用されている検証グループの一部ではない制約を含む)。

Form Type Options Guessing

When the guessing mechanism is enabled for some field, in addition to its form type, the following options will be guessed too:

一部のフィールドで推測メカニズムが有効になっている場合、そのフォーム タイプに加えて、次のオプションも推測されます。
required
The required option is guessed based on the validation rules (i.e. is the field NotBlank or NotNull) or the Doctrine metadata (i.e. is the field nullable). This is very useful, as your client-side validation will automatically match your validation rules.
必要なオプションは、検証ルール (つまり、フィールド NotBlank または NotNull) または Doctrine メタデータ (つまり、フィールドが null 可能か) に基づいて推測されます。クライアント側の検証が検証ルールに自動的に一致するため、これは非常に便利です。
maxlength
If the field is some sort of text field, then the maxlength option attribute is guessed from the validation constraints (if Length or Range is used) or from the Doctrine metadata (via the field's length).
フィールドがある種のテキストフィールドである場合、maxlength オプション属性は検証制約 (Length または Range が使用されている場合) または Doctrine メタデータ (フィールドの長さを介して) から推測されます。

If you'd like to change one of the guessed values, override it in the options field array:

推測された値の 1 つを変更したい場合は、オプション フィールド配列でオーバーライドします。
1
->add('task', null, ['attr' => ['maxlength' => 4]])

See also

こちらもご覧ください

Besides guessing the form type, Symfony also guesses validation constraints if you're using a Doctrine entity. Read Databases and the Doctrine ORM guide for more information.

Doctrine エンティティを使用している場合、Symfony はフォーム タイプを推測するだけでなく、検証制約も推測します。詳細については、データベースとDoctrine ORMガイドをお読みください。

Unmapped Fields

When editing an object via a form, all form fields are considered properties of the object. Any fields on the form that do not exist on the object will cause an exception to be thrown.

フォームを介してオブジェクトを編集する場合、すべてのフォーム フィールドはオブジェクトのプロパティと見なされます。オブジェクトに存在しないフォームのフィールドがあると、例外がスローされます。

If you need extra fields in the form that won't be stored in the object (for example to add an "I agree with these terms" checkbox), set the mapped option to false in those fields:

オブジェクトに保存されない追加のフィールドがフォームに必要な場合 (たとえば、「これらの条件に同意します」チェックボックスを追加する場合)、これらのフィールドでマップされたオプションを false に設定します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// ...
use Symfony\Component\Form\FormBuilderInterface;

class TaskType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('task')
            ->add('dueDate')
            ->add('agreeTerms', CheckboxType::class, ['mapped' => false])
            ->add('save', SubmitType::class)
        ;
    }
}

These "unmapped fields" can be set and accessed in a controller with:

これらの「マップされていないフィールド」は、コントローラーで次のように設定およびアクセスできます。
1
2
$form->get('agreeTerms')->getData();
$form->get('agreeTerms')->setData(true);

Additionally, if there are any fields on the form that aren't included in the submitted data, those fields will be explicitly set to null.

さらに、送信されたデータに含まれていないフィールドがフォームにある場合、それらのフィールドは明示的に null に設定されます。

Learn more

When building forms, keep in mind that the first goal of a form is to translate data from an object (Task) to an HTML form so that the user can modify that data. The second goal of a form is to take the data submitted by the user and to re-apply it to the object.

フォームを作成するときは、フォームの最初の目的は、ユーザーがそのデータを変更できるように、データをオブジェクト (タスク) から HTML フォームに変換することであることに注意してください。フォームの 2 番目の目的は、ユーザーが送信したデータを取得し、それをオブジェクトに再適用することです。

There's a lot more to learn and a lot of powerful tricks in the Symfony forms:

Symfony フォームには、学ぶべきことがたくさんあり、強力なトリックがたくさんあります。

Reference:

参照:

Advanced Features:

高度な機能:

Form Themes and Customization:

フォームのテーマとカスタマイズ:

Events:

イベント:

Validation:

検証:

Misc.:

その他: