Files
archived-symfony-docs/form/inherit_data_option.rst
Timo Bakx 3849004fcc Replaced caution blocks with warning
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.
2024-12-07 12:02:55 +01:00

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.