mirror of
https://github.com/symfony/symfony-docs.git
synced 2026-03-24 00:32:14 +01:00
Fixes #20371 Both blocks are currently rendered identically. Keeping only one of the two makes it easier to contribute. Some blocks were elevated to danger.
171 lines
4.9 KiB
ReStructuredText
171 lines
4.9 KiB
ReStructuredText
How to Reduce Code Duplication with "inherit_data"
|
|
==================================================
|
|
|
|
The ``inherit_data`` form field option can be very useful when you have some
|
|
duplicated fields in different entities. For example, imagine you have two
|
|
entities, a ``Company`` and a ``Customer``::
|
|
|
|
// 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;
|
|
}
|
|
|
|
.. code-block:: php
|
|
|
|
// 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;
|
|
}
|
|
|
|
As you can see, each entity shares a few of the same fields: ``address``,
|
|
``zipcode``, ``city``, ``country``.
|
|
|
|
Start with building two forms for these entities, ``CompanyType`` and ``CustomerType``::
|
|
|
|
// 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);
|
|
}
|
|
}
|
|
|
|
.. code-block:: php
|
|
|
|
// 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);
|
|
}
|
|
}
|
|
|
|
Instead of including the duplicated fields ``address``, ``zipcode``, ``city``
|
|
and ``country`` in both of these forms, create a third form called ``LocationType``
|
|
for that::
|
|
|
|
// 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,
|
|
]);
|
|
}
|
|
}
|
|
|
|
The location form has an interesting option set, namely ``inherit_data``. This
|
|
option lets the form inherit its data from its parent form. If embedded in
|
|
the company form, the fields of the location form will access the properties of
|
|
the ``Company`` instance. If embedded in the customer form, the fields will
|
|
access the properties of the ``Customer`` instance instead. Convenient, eh?
|
|
|
|
.. note::
|
|
|
|
Instead of setting the ``inherit_data`` option inside ``LocationType``, you
|
|
can also (just like with any option) pass it in the third argument of
|
|
``$builder->add()``.
|
|
|
|
Finally, make this work by adding the location form to your two original forms::
|
|
|
|
// 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,
|
|
]);
|
|
}
|
|
}
|
|
|
|
.. code-block:: php
|
|
|
|
// 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,
|
|
]);
|
|
}
|
|
}
|
|
|
|
That's it! You have extracted duplicated field definitions to a separate
|
|
location form that you can reuse wherever you need it.
|
|
|
|
.. warning::
|
|
|
|
Forms with the ``inherit_data`` option set cannot have ``*_SET_DATA`` event listeners.
|