How to Embed Forms

Often, you'll want to build a form that will include fields from many different objects. For example, a registration form may contain data belonging to a User object as well as many Address objects. Fortunately this can be achieved by the Form component.

多くの場合、さまざまなオブジェクトのフィールドを含むフォームを作成したいと思うでしょう。たとえば、登録フォームには、User オブジェクトと多くの Address オブジェクトに属するデータが含まれている場合があります。幸いなことに、これは Form コンポーネントによって実現できます。

Embedding a Single Object

Suppose that each Task belongs to a Category object. Start by creating the Category class:

各 Task が Category オブジェクトに属しているとします。まず、Category クラスを作成します。
1
2
3
4
5
6
7
8
9
10
// src/Entity/Category.php
namespace App\Entity;

use Symfony\Component\Validator\Constraints as Assert;

class Category
{
    #[Assert\NotBlank]
    public $name;
}

Next, add a new category property to the Task class:

次に、Task クラスに新しいカテゴリ プロパティを追加します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// ...

class Task
{
    // ...

    #[Assert\Type(type: Category::class)]
    #[Assert\Valid]
    protected $category;

    // ...

    public function getCategory(): ?Category
    {
        return $this->category;
    }

    public function setCategory(?Category $category)
    {
        $this->category = $category;
    }
}

Tip

ヒント

The Valid Constraint has been added to the property category. This cascades the validation to the corresponding entity. If you omit this constraint, the child entity would not be validated.

プロパティ カテゴリに Valid Constraint が追加されました。これにより、検証が対応するエンティティにカスケードされます。この制約を省略すると、子エンティティは検証されません。

Now that your application has been updated to reflect the new requirements, create a form class so that a Category object can be modified by the user:

アプリケーションが更新されて新しい要件が反映されたので、フォーム クラスを作成して、ユーザーが Category オブジェクトを変更できるようにします。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// src/Form/CategoryType.php
namespace App\Form;

use App\Entity\Category;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class CategoryType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder->add('name');
    }

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

The end goal is to allow the Category of a Task to be modified right inside the task form itself. To accomplish this, add a category field to the TaskType object whose type is an instance of the new CategoryType class:

最終的な目標は、タスクのカテゴリをタスク フォーム自体の中で変更できるようにすることです。これを実現するには、タイプが新しい CategoryType クラスのインスタンスである TaskType オブジェクトにカテゴリ フィールドを追加します。
1
2
3
4
5
6
7
8
9
use App\Form\CategoryType;
use Symfony\Component\Form\FormBuilderInterface;

public function buildForm(FormBuilderInterface $builder, array $options): void
{
    // ...

    $builder->add('category', CategoryType::class);
}

The fields from CategoryType can now be rendered alongside those from the TaskType class.

CategoryType のフィールドは、TaskType クラスのフィールドと一緒にレンダリングできるようになりました。

Render the Category fields in the same way as the original Task fields:

カテゴリ フィールドを元のタスク フィールドと同じ方法でレンダリングします。
1
2
3
4
5
6
7
8
{# ... #}

<h3>Category</h3>
<div class="category">
    {{ form_row(form.category.name) }}
</div>

{# ... #}

When the user submits the form, the submitted data for the Category fields are used to construct an instance of Category, which is then set on the category field of the Task instance.

ユーザーがフォームを送信すると、Category フィールドに送信されたデータを使用して Category のインスタンスが作成され、Task インスタンスのcategory フィールドに設定されます。

The Category instance is accessible naturally via $task->getCategory() and can be persisted to the database or used however you need.

Category インスタンスは $task->getCategory() 経由で自然にアクセスでき、データベースに永続化するか、必要に応じて使用できます。

Embedding a Collection of Forms

You can also embed a collection of forms into one form (imagine a Category form with many Product sub-forms). This is done by using the collection field type.

フォームのコレクションを 1 つのフォームに埋め込むこともできます (多数の Product サブフォームを含む Categoryform を想像してください)。これは、collectionfield タイプを使用して行われます。

For more information see the How to Embed a Collection of Forms article and the CollectionType reference.

詳細については、フォームのコレクションを埋め込む方法の記事と CollectionType リファレンスを参照してください。