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