Як зменшити дублювання коду за допомогою "inherit_data"

Дата оновлення перекладу 2022-11-20

Як зменшити дублювання коду за допомогою "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.