We have 2 entities. A Company and a Customer:
namespace ...;
class Company
{
private $name;
private $website;
private $address;
private $zipcode;
private $city;
private $country;
// Some nice getters / setters here.
}
namespace ...;
class Customer
{
private $firstName;
private $lastName;
private $address;
private $zipcode;
private $city;
private $country;
// Some nice getters / setters here.
}
Like you can see, both of our entities have these fields:
address
, zipcode
, city
, country
.Now, we want to build 2 forms. One for create/update a Company and the second to create/update a Customer.
Of course, we have only two entities which have to contains some location informations... for now! Maybe later, some entities will have this fields. So, we have to find a solution to not duplicate our code!
First, we create very simple CompanyType and CustomerType:
namespace ...;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;
class CompanyType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder
->add('name', 'text')
->add('website', 'text')
;
}
public function getDefaultOptions(array $options)
{
return array(
'data_class' => '...\Company',
);
}
public function getName()
{
return 'company';
}
}
namespace ...;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;
class CustomerType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder
->add('firstName', 'text')
->add('lastName', 'text')
;
}
public function getDefaultOptions(array $options)
{
return array(
'data_class' => '...\Customer',
);
}
public function getName()
{
return 'customer';
}
}
Definitely nothing complicated here.
Now, we have to deal with our four duplicated fields... Here is a (simple) location FormType:
namespace ...;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;
class LocationType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder
->add('address', 'textarea')
->add('zipcode', 'string')
->add('city', 'string')
->add('country', 'text')
;
}
public function getDefaultOptions(array $options)
{
return array(
'virtual' => true
);
}
public function getName()
{
return 'location';
}
}
We can't specify a data_class option in this FormType because, we don't have a Location Entity.
We don't have a location field in our entity so we can't directly link our LocationType.
Of course, we absolutely want to have a dedicated FormType to deal with location (remember, DRY!)
We don't have a location field in our entity so we can't directly link our LocationType.
Of course, we absolutely want to have a dedicated FormType to deal with location (remember, DRY!)
There is a solution!
We can set the option
'virtual' => true
in the getDefaultOptions
method of our LocationType and directly start use it in our 2 first types.Look at the result:
// CompanyType
public function buildForm(FormBuilder $builder, array $options)
{
$builder->add('foo', new LocationType());
}
// CustomerType
public function buildForm(FormBuilder $builder, array $options)
{
$builder->add('bar', new LocationType());
}
With the virtual option set to false (default behavior), the Form Component expect a Foo (or Bar) object or array which contains our four location fields. Of course, we don't have this object/array in our entities and we don't want it!
With the virtual option set to true, the Form Component skip our Foo (or Bar) object or array. So, it directly access to our 4 location fields which are in the parent entity!
(One more time, thank to Alexandre Salomé for the tips)
More than 3 requests, I'll translate this to Chinese.
超过3个请求,我就会把这篇文章翻译成中文。
No comments:
Post a Comment