Via G. Falcone 5, Pollenza (MC), Italy
+39 0733 203595

Symfony form pills – Value object

Suppose that we have a value object or, more in general, an object where its data has been set in the constructor

and its FormType

Let’s assume that bar and foobar are taken from HTTP POST values (so, basically, we need those values to be posted in order to instantiate a Foo object).

Question

How can I create the form?

I need to pass an instance of Foo class to the form factory but the Foo class needs, in turn, form values submitted by the user POST action.

This seems like a “circular chain of needs”.

Solution

You can use the empty_data attribute of FormType

Explanation

We make form factory accept a null value during form creation

Then, when we post data, the FormComponent will look for empty_data option and will instantiate a Foo object with values passed from post.

“Edit” of Value Object

This will work only if you need to create a new object, if you need to use the same view also for “edit” (quotes because you cannot edit a Value Object; you need to create a brand new one) you have to define a DataMapper and implement two “mapping” functions called mapDataToForms and mapFormsToData

Finally (in both scenarios) if we need to retrieve our object, we can act as follows

If you haven’t read it yet – or if you’ve already done – this article could fit some “fuzziness” of this older article

Related Posts

6 comments

Maxime Steinhausser

Beware that the empty_data option will not suit every needs. Indeed, it works great for creating an object when initial data are empty, but trying to update data (and thus replace the initial value object by another instance) won’t work.
I recommend you to read this great article about value objects in Symfony Forms written by webmozart: https://webmozart.io/blog/2015/09/09/value-objects-in-symfony-forms/.

You can also give a look to this package made in the aim to ease immutable and value objects manipulation with the Symfony Form component –> https://github.com/Elao/FormSimpleObjectMapper. 😉

Hi Maxime.
You’re totally right, I’ve missed the update part but I was aware of that way of handle Value Objects in update phase; I’ll update later.

Thank your for comment and for pointing out your bundle.
Cheers!
S.

While conceptually it’s nice to have value objects like that, I think it’s better to simply use the benefits of the property accessor. As your object will never be in a valid state either way, I think it’s better so use it as a mere data container: https://stovepipe.systems/post/avoiding-entities-in-forms

Hi Iltar, thank you for this comment.
Well, actually, it’s not completely true that “object will never be in a valid state either way” because, through constructor, there are cases where I can be sure that if object is created, it will be valid and ready to be persisted.
“Avoiding entities in forms” seems to be too much restrictive and should be handled from case to case.

Cheers.
S.

be aware that the empty data callback is applied before validation and so $interface->get(‘bar’)->getData() can return a value that may not fit your value object constructor

Hi Thomas, thank you for your comment.
Well, although it’s true that validation is performed *after* data binding, there is no difference with “standard” form handling.
What I mean is that in Symfony the process is post –> bind (so, call setters) –> validation. As you can see, also calls to setters is “afflicted” from this problem. One typical scenario is when you cannot accept a null value and you have Assert\NotNull() on the property: if you post a null value you get an error.
To solve this usually you can use a DTO that is less restrictive than your entity (model) and that will perform some controls before pour contents into entity.

What I wanted to highlight with this comment is that’s not a problem of empty_data or Immutable Objects or Value Objects. Hope is clear 🙂

Leave a reply