Как уменьшить дублирование кода с помощью "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 $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/Entity/Customer.php
namespace App\Entity;

class Customer
{
    private $firstName;
    private $lastName;

    private $address;
    private $zipcode;
    private $city;
    private $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\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/Form/Type/CustomerType.php
namespace App\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/Form/Type/LocationType.php
namespace App\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. Легко, правда же?

Note

Вместо того, чтобы устанавливать опцию inherit_data внутри LocationType, вы также можете (как и с любой другой опцией) передать её в третьем аргументе $builder->add().

Наконец, закончите работе, добавив форму локации в две ваши первоначальные формы:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// src/Form/Type/CompanyType.php
use App\Entity\Company;
// ...

public function buildForm(FormBuilderInterface $builder, array $options)
{
    // ...

    $builder->add('foo', LocationType::class, array(
        'data_class' => Company::class,
    ));
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// src/Form/Type/CustomerType.php
use App\Entity\Customer;
// ...

public function buildForm(FormBuilderInterface $builder, array $options)
{
    // ...

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

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

Caution

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

Эта документация является переводом официальной документации Symfony и предоставляется по свободной лицензии CC BY-SA 3.0.