How to Use a Form without a Data Class

In most cases, a form is tied to an object, and the fields of the form get and store their data on the properties of that object. This is exactly what you've seen so far in this article with the Task class.

ほとんどの場合、フォームはオブジェクトに関連付けられており、フォームのフィールドはそのオブジェクトのプロパティでデータを取得および保存します。これはまさに、これまでこの記事で Task クラスについて説明してきたことです。

But sometimes, you may want to use a form without a class, and get back an array of the submitted data. The getData() method allows you to do exactly that:

しかし、場合によっては、クラスなしでフォームを使用して、送信されたデータの配列を取得したい場合があります。 getData() メソッドを使用すると、次のことを正確に行うことができます。
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/ContactController.php
namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
// ...

class ContactController extends AbstractController
{
    public function contact(Request $request): Response
    {
        $defaultData = ['message' => 'Type your message here'];
        $form = $this->createFormBuilder($defaultData)
            ->add('name', TextType::class)
            ->add('email', EmailType::class)
            ->add('message', TextareaType::class)
            ->add('send', SubmitType::class)
            ->getForm();

        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            // data is an array with "name", "email", and "message" keys
            $data = $form->getData();
        }

        // ... render the form
    }
}

By default, a form actually assumes that you want to work with arrays of data, instead of an object. There are exactly two ways that you can change this behavior and tie the form to an object instead:

デフォルトでは、フォームは、オブジェクトではなく、データの配列を操作することを想定しています。この動作を変更し、代わりにフォームをオブジェクトに結び付けるには、正確に 2 つの方法があります。
  1. Pass an object when creating the form (as the first argument to createFormBuilder() or the second argument to createForm());
    フォームの作成時にオブジェクトを渡します (createFormBuilder() の最初の引数または createForm() の 2 番目の引数として)。
  2. Declare the data_class option on your form.
    フォームで data_class オプションを宣言します。

If you don't do either of these, then the form will return the data as an array. In this example, since $defaultData is not an object (and no data_class option is set), $form->getData() ultimately returns an array.

これらのいずれも行わない場合、フォームはデータを配列として返します。この例では、$defaultData はオブジェクトではない (また、data_class オプションが設定されていない) ため、$form->getData() は最終的に配列を返します。

Tip

ヒント

You can also access POST values (in this case "name") directly through the request object, like so:

次のように、リクエスト オブジェクトを介して POST 値 (この場合は「名前」) に直接アクセスすることもできます。
1
$request->request->get('name');

Be advised, however, that in most cases using the getData() method is a better choice, since it returns the data (usually an object) after it's been transformed by the Form component.

ただし、フォーム コンポーネントによって変換された後にデータ (通常はオブジェクト) を返すため、ほとんどの場合、getData() メソッドを使用する方が適切です。

Adding Validation

The only missing piece is validation. Usually, when you call $form->handleRequest($request), the object is validated by reading the constraints that you applied to that class. If your form is mapped to an object (i.e. you're using the data_class option or passing an object to your form), this is almost always the approach you want to use. See Validation for more details.

欠けている唯一の部分は検証です。通常、$form->handleRequest($request) を呼び出すと、そのクラスに適用した制約を読み取ることによってオブジェクトが検証されます。フォームがオブジェクトにマップされている場合 (つまり、data_class オプションを使用しているか、オブジェクトをフォームに渡している場合)、ほとんどの場合、これが使用したいアプローチです。詳細については、検証を参照してください。

But if the form is not mapped to an object and you instead want to retrieve an array of your submitted data, how can you add constraints to the data of your form?

しかし、フォームがオブジェクトにマップされておらず、代わりに送信されたデータの配列を取得したい場合、フォームのデータに制約を追加するにはどうすればよいでしょうか?

The answer is to set up the constraints yourself, and attach them to the individual fields. The overall approach is covered a bit more in this validation article, but here's a short example:

答えは、自分で制約を設定し、それらを個々のフィールドに添付することです。全体的なアプローチについては、この検証記事でもう少し詳しく説明しますが、短い例を次に示します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Validator\Constraints\Length;
use Symfony\Component\Validator\Constraints\NotBlank;

public function buildForm(FormBuilderInterface $builder, array $options): void
{
    $builder
        ->add('firstName', TextType::class, [
            'constraints' => new Length(['min' => 3]),
        ])
        ->add('lastName', TextType::class, [
            'constraints' => [
                new NotBlank(),
                new Length(['min' => 3]),
            ],
        ])
    ;
}

Tip

ヒント

If you are using validation groups, you need to either reference the Default group when creating the form, or set the correct group on the constraint you are adding:

検証グループを使用している場合は、フォームの作成時にデフォルト グループを参照するか、追加する制約に正しいグループを設定する必要があります。
1
new NotBlank(['groups' => ['create', 'update']]);

Tip

ヒント

If the form is not mapped to an object, every object in your array of submitted data is validated using the Symfony\Component\Validator\Constraints\Valid constraint, unless you disable validation.

フォームがオブジェクトにマップされていない場合、送信されたデータの配列内のすべてのオブジェクトは、検証を無効にしない限り、Symfony\Component\Validator\Constraints\Validconstraint を使用して検証されます。

Caution

注意

When a form is only partially submitted (for example, in an HTTP PATCH request), only the constraints from the submitted form fields will be evaluated.

フォームが部分的にしか送信されない場合 (HTTP PATCH リクエストなど)、送信されたフォーム フィールドの制約のみが評価されます。