Description
NOTE: I'm aware that 2.1 introduces quite a few BC breaks in the Form component. Unfortunately these are necessary in order to fix a number of bugs present in 2.0. Doing these changes now will hopefully help to stabilize the API after 2.1.
I suggest to make property paths first class citizens of Forms. I will start with explaining the API change and continue with the reasoning why I think this should be done.
Old API:
<?php
$builder
// mapped to $data->getCity() or $data['city']
->add('city')
// mapped to $data->getAddress()->getStreet()
// or $data->getAddress()['street']
// or $data['address']->getStreet()
// or $data['address']['street']
->add('street', array(
'property_path' => 'address.street'
))
// not mapped at all
->add('terms', array(
'property_path' => false,
));
// Form backed by an array
$builder
->add('city')
->add('street', array(
// can be used, but makes no difference
'property_path' => '[street]',
));
New API:
<?php
$builder
// mapped to $data->getCity()
->add('city')
// mapped to $data['city']
->add('[city]')
// mapped to $data->getAddress()->getStreet()
->add('address.street')
// mapped to $data['address']->getStreet()
->add('[address].street')
// mapped to $data->getAddress()['street']
->add('address[street]')
// mapped to $data['address']['street']
->add('[address][street]')
// not mapped at all
->add('terms', array(
'mapped' => false,
))
// custom, beautified HTML/POST parameter name (important for REST APIs)
->add('address.street', array(
'name' => 'street',
));
// Form backed by an array
$builder
->add('[city]')
->add('[street]');
Negative consequences:
- people who used the "property_path" option must adapt their code
- forms backed by arrays must be adapted: field names need to be changed from "fieldname" to "[fieldname]"
Positive consequences:
- a clearer API for newcomers, no hidden "property_path" option anymore
- a deterministic mechanism for violation mapping, allowing more sophisticated techniques to assign errors to specific fields (to fix errors like [Form][DelegatingValidator] RepeatedType error keeps on bubbling to root form #1971)
Reasoning:
The validator generates violation errors with property paths that must be mapped to the corresponding form fields. Right now, this mapping grows exponentially in the length of the property path:
PP of constraint violation | Guessed PP of mapped form field |
---|---|
city | city [city] |
[city] | [city] |
address.city | address.city address[city] [address].city address[city] |
address[city] | address[city] [address][city] |
[address].city | [address].city [address][city] |
[address][city] | [address][city] |
person.address.city | person.address.city person.address[city] person[address].city person[address][city] [person].address.city [person].address[city] [person][address].city [person][address][city] |
Changing the API would make property paths deterministic and greatly simplify the mapping:
PP of constraint violation | Guessed PP of mapped form field |
---|---|
city | city |
[city] | [city] |
address.city | address.city |
address[city] | address[city] |
[address].city | [address].city |
[address][city] | [address][city] |
A simplified mapping mechanism allows more elaborate mapping options, like specifying that
- errors mapped to a form should be mapped to a child "foo" instead
- errors mapped to a child "foo" should be mapped to a child "bar" instead
Feedback is appreciated.