Skip to content

[Form] RFC: Adapt Form API to avoid exponential growth of the violation mapping #3903

Closed
@webmozart

Description

@webmozart

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:

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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions