如何使用inherit_data去减少代码冗余

3.4 版本
维护中的版本

当你在不同的实体有一些重复的字段,inherit_data表单字段选项就非常有用。例如,假设你有两个实体,一个Company(公司)和一个Customer(客户):

1
2
3
4
5
6
7
8
9
10
11
12
13
// src/AppBundle/Entity/Company.php
namespace AppBundle\Entity;
 
class Company
{
    private $name;
    private $website;
 
    private $address;
    private $zipcode;
    private $city;
    private $country;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
// src/AppBundle/Entity/Customer.php
namespace AppBundle\Entity;
 
class Customer
{
    private $firstName;
    private $lastName;
 
    private $address;
    private $zipcode;
    private $city;
    private $country;
}

正如你看到的,每个实体都有一些相同的字段:address, zipcode, city, country

我们开始为这些实体构建两个表单,CompanyTypeCustomerType

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// src/AppBundle/Form/Type/CompanyType.php
namespace AppBundle\Form\Type;
 
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\TextType;
 
class CompanyType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('name', TextType::class)
            ->add('website', TextType::class);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// src/AppBundle/Form/Type/CustomerType.php
namespace AppBundle\Form\Type;
 
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
 
class CustomerType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('firstName', TextType::class)
            ->add('lastName', TextType::class);
    }
}

这里面我们不在两个表单中包含重复的字段address, zipcode, city, country,我们创建第三个表单LocationType 来包含他们:

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
// src/AppBundle/Form/Type/LocationType.php
namespace AppBundle\Form\Type;
 
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
 
class LocationType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('address', TextareaType::class)
            ->add('zipcode', TextType::class)
            ->add('city', TextType::class)
            ->add('country', TextType::class);
    }
 
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'inherit_data' => true
        ));
    }
}

在这个位置表单里有一个很有趣的配置选项,就是inherit_data。这个选项使得表单可以从它的父表单那里继承数据。如果嵌入到公司表单中,这个位置表单的字段将会变成Company实例的属性。如果嵌入到顾客表单中,这个位置表单的字段将会变成Customer实例的属性。很简单吧?

还有别的方式设置inherit_data配置选项,不一定要在LocationType中,你还可以(就像其它选项一样)将它传递到 $builder->add() 的第三参数中。

最后,通过将位置表单添加到你的原始表单中来完成这个工作:

1
2
3
4
5
6
7
8
9
// src/AppBundle/Form/Type/CompanyType.php
public function buildForm(FormBuilderInterface $builder, array $options)
{
    // ...
 
    $builder->add('foo', LocationType::class, array(
        'data_class' => 'AppBundle\Entity\Company'
    ));
}
1
2
3
4
5
6
7
8
9
// src/AppBundle/Form/Type/CustomerType.php
public function buildForm(FormBuilderInterface $builder, array $options)
{
    // ...
 
    $builder->add('bar', LocationType::class, array(
        'data_class' => 'AppBundle\Entity\Customer'
    ));
}

就是这样!你已经把重复字段的定义提取到一个单独的位置,无论什么时候,只要你需要你就可以重用它。

表单inherit_data 选项设置不能有*_SET_DATA事件监听。

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

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