如何嵌入表单

3.4 版本
维护中的版本

通常,你可能想生成一个表单,它包含来自不同对象的字段。比如,一个注册表单可能包含属于User对象和Address对象的字段。幸运的是,这些对于form组件来说都是很容易很自然的事。

嵌入一个单独对象 

假设每个Task属于一个Category对象,首先创建这个Category对象:

1
2
3
4
5
6
7
8
9
10
11
12
// src/AppBundle/Entity/Category.php
namespace AppBundle\Entity;
 
use Symfony\Component\Validator\Constraints as Assert;
 
class Category
{
    /**
     * @Assert\NotBlank()
     */
    public $name;
}

接下来,添加一个新的category属性到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
// ...
 
class Task
{
    // ...
 
    /**
     * @Assert\Type(type="AppBundle\Entity\Category")
     * @Assert\Valid()
     */
    protected $category;
 
    // ...
 
    public function getCategory()
    {
        return $this->category;
    }
 
    public function setCategory(Category $category = null)
    {
        $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
// src/AppBundle/Form/Type/CategoryType.php
namespace AppBundle\Form\Type;
 
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)
    {
        $builder->add('name');
    }
 
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\Category',
        ));
    }
}

我们的最终目的是能够让用户在Task表单中修改Category对象,所以,我们需要添加一个类型为CategoryType表单类的category字段到TaskType 表单类。

1
2
3
4
5
6
7
8
9
use Symfony\Component\Form\FormBuilderInterface;
use AppBundle\Form\Type\CategoryType;
 
public function buildForm(FormBuilderInterface $builder, array $options)
{
    // ...
 
    $builder->add('category', CategoryType::class);
}

这时,CategoryType就可以和TaskType类一起渲染了。

和呈现原来的Task字段一样呈现Category字段:

1
2
3
4
5
6
7
8
{# ... #}
 
<h3>Category</h3>
<div class="category">
    {{ form_row(form.category.name) }}
</div>
 
{# ... #}
1
2
3
4
5
6
7
8
<!-- ... -->
 
<h3>Category</h3>
<div class="category">
    <?php echo $view['form']->row($form['category']['name']) ?>
</div>
 
<!-- ... -->

当用户提交表单时,提交的Category字段数据被用于创建一个Category实例,然后被设置到Task实例的category字段。

Category实例可以通过Task实例来访问$task->getCategory(),同时也能被持久化到数据或者用作它用。

嵌入一个表单集合 

你也可以将一个表单集合嵌入到一个表单(想象一个Category 表单和许多Product子表单)。它是通过一个字段类型集合类实现的。

想了解更多请参阅如何嵌入表单集合CollectionType 参考

本文,包括例程代码在内,采用的是 Creative Commons BY-SA 3.0 创作共用授权。

登录symfonychina 发表评论或留下问题(我们会尽量回复)