跳到内容

如何使用 “inherit_data” 减少代码重复

编辑此页

当你在不同的实体中有一些重复字段时,inherit_data 表单字段选项非常有用。 例如,假设你有两个实体,一个 Company 和一个 Customer

1
2
3
4
5
6
7
8
9
10
11
12
13
// src/Entity/Company.php
namespace App\Entity;

class Company
{
    private string $name;
    private string $website;

    private string $address;
    private string $zipcode;
    private string $city;
    private string $country;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
// src/Entity/Customer.php
namespace App\Entity;

class Customer
{
    private string $firstName;
    private string $lastName;

    private string  $address;
    private string $zipcode;
    private string $city;
    private string $country;
}

正如你所看到的,每个实体都共享一些相同的字段:addresszipcodecitycountry

首先为这些实体构建两个表单,CompanyTypeCustomerType

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// src/Form/Type/CompanyType.php
namespace App\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;

class CompanyType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $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/Form/Type/CustomerType.php
namespace App\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;

class CustomerType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('firstName', TextType::class)
            ->add('lastName', TextType::class);
    }
}

与其在这两个表单中都包含重复的字段 addresszipcodecitycountry,不如为此创建一个名为 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/Form/Type/LocationType.php
namespace App\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class LocationType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('address', TextareaType::class)
            ->add('zipcode', TextType::class)
            ->add('city', TextType::class)
            ->add('country', TextType::class);
    }

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

位置表单有一个有趣的选项设置,即 inherit_data。 此选项允许表单从其父表单继承数据。 如果嵌入到公司表单中,位置表单的字段将访问 Company 实例的属性。 如果嵌入到客户表单中,这些字段将访问 Customer 实例的属性。 很方便,对吧?

注意

除了在 LocationType 内部设置 inherit_data 选项之外,你也可以(就像任何选项一样)在 $builder->add() 的第三个参数中传递它。

最后,通过将位置表单添加到你的两个原始表单中来使其工作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// src/Form/Type/CompanyType.php
namespace App\Form\Type;

use App\Entity\Company;
use Symfony\Component\Form\AbstractType;

// ...

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

        $builder->add('foo', LocationType::class, [
            'data_class' => Company::class,
        ]);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// src/Form/Type/CustomerType.php
namespace App\Form\Type;

use App\Entity\Customer;
use Symfony\Component\Form\AbstractType;

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

        $builder->add('bar', LocationType::class, [
            'data_class' => Customer::class,
        ]);
    }
}

就是这样! 你已经将重复的字段定义提取到一个单独的位置表单中,你可以在任何需要它的地方重用它。

警告

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

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