Как уменьшить дублирование кода с помощью "inherit_data"

Дата обновления перевода 2023-09-07

Как уменьшить дублирование кода с помощью "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;
}

Как вы можете увидеть, каждая сущность имеет несколько одинаковых полей: address, zipcode, city, country.

Начните с построения двух форм для этих сущностей, CompanyType и CustomerType:

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

Вместо того, чтобы включать дублированные поля 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/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. Легко, правда же?

Note

Вместо того, чтобы устанавливать опцию inherit_data внутри LocationType, вы также можете (как и с любой другой опцией) передать её в третьем аргументе $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,
        ]);
    }
}

Вот и всё! Вы извлекли дублированные определения полей в отдельную форму локации, которую вы можете использовать повторно, когда вам это понадобится.

Caution

Формы с установленной опцией inherit_data не могут иметь слушателей событий *_SET_DATA.