跳到内容

如何嵌入表单

编辑此页

通常,您会希望构建一个表单,其中包含来自许多不同对象的字段。例如,注册表单可能包含属于 User 对象以及许多 Address 对象的数据。幸运的是,这可以通过 Form 组件来实现。

嵌入单个对象

假设每个 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 string $name;
}

接下来,向 Task 类添加一个新的 category 属性

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 $category = null;

    // ...

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

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

提示

Valid 约束已添加到属性 category。这将级联验证到相应的实体。如果您省略此约束,则不会验证子实体。

现在您的应用程序已更新以反映新的要求,创建一个表单类,以便用户可以修改 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,
        ]);
    }
}

最终目标是允许在任务表单本身中修改 TaskCategory。为了实现这一点,向 TaskType 对象添加一个 category 字段,其类型是新 CategoryType 类的实例

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);
}

现在可以与 TaskType 类中的字段一起呈现来自 CategoryType 的字段。

以与原始 Task 字段相同的方式呈现 Category 字段

1
2
3
4
5
6
7
8
{# ... #}

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

{# ... #}

当用户提交表单时,Category 字段的提交数据用于构造 Category 的实例,然后将其设置在 Task 实例的 category 字段上。

Category 实例可以通过 $task->getCategory() 自然地访问,并且可以持久化到数据库或以您需要的任何方式使用。

嵌入表单集合

您还可以将表单集合嵌入到一个表单中(想象一下一个包含许多 Product 子表单的 Category 表单)。这可以通过使用 collection 字段类型来完成。

有关更多信息,请参阅如何嵌入表单集合文章和CollectionType参考。

本作品,包括代码示例,根据 Creative Commons BY-SA 3.0 许可协议获得许可。
目录
    版本