Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

[Form] Overriding only getter causes exceptions while submitting #48167

Copy link
Copy link
Closed
@curry684

Description

@curry684
Issue body actions

Symfony version(s) affected

5.2.0 upwards

Description

Symfony 5.2 introduced the getter and setter options for form types, but the separation is not complete causing exceptions during form submission.

How to reproduce

Consider this use case on an object tree inheriting settings:

    private ?int $value;
    
    public function setValue(?int $newValue): void
    {
        $this->value = $newValue;
    }

    public function getConfiguredValue(): ?int
    {
        return $this->value;
    }

    public function getActualValue(): int
    {
        return $this->value ?? $this->parent->getActualValue();
    }

In this case, the getter is not called getValue on purpose, to avoid confusion with programmers calling the wrong one. Since Symfony 5.2 I can now map this in a form:

    $builder
        ->add('value', IntegerType::class, [
            'getter' => fn($object) => $object->getConfiguredValue(),
        ])

This works fine to render the form. Submitting it however crashes with a NoSuchPropertyException, stating Can't get a way to read the property "value" in class XXX. Note that it doesn't know how to read the property: this is because there is no setter defined, as the default works fine, and as such the PropertyPathAccessor is used to set the value, which reads the property to detect changes first, is blissfully unaware of the getter option, and therefore tries to read the propery via the accessor.

Possible Solution

Right now the only working solution without modifying the original object is to add a setter as well, which is pure boilerplate as it does nothing special:

          'setter' => function($object, ?int $newValue) {
              $object->setValue($newValue);
          },

So solutions we could implement are:

  • Make getter and setter mandatory in pairs - setting one requires the other. This is currently in practice enforced by the implementation, yet it does not throw an error if you don't. Seems weak as in the given example the setter is completely obsolete.
  • Make the DataAccessor properly aware of the existence of a getter when defaulting the set behavior, bypassing default PropertyAccess behavior that tries to read the property for changes.

Obviously the second solution is far more correct and better, it is also more complex and may introduce new edge cases.

Additional Context

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      Morty Proxy This is a proxified and sanitized view of the page, visit original site.