kiw
kiw

Reputation: 808

Symfony CollectionType update Entities

I can't believe this hasn't come up for other people, but I'm unable to find a solution.

Let's say I have two entity types, A and B with a one-to-many relationship. A has a collection of Bs.

The form for A has a CollectionType for the Bs, with a custom entry_type for B, allow_add and allow_delete set to true. When the form is created/populated/rendered, the Bs' fields are identified by their index in the collection. When the form is posted back, the fields are mapped back onto the B entities according to the index again.

What if the database in the mean time decided to return the Bs in a different order? Then the values get swapped around on the Bs! I can't have that, as other entities will reference the Bs and now they've changed their meaning!

Even if the database doesn't change the order, the same issue appears when a B is deleted: The fields get shifted through the Bs and a different one deleted! (Ok, I'm not a 100% certain this happens, as there's a gap then in the numbering of the posted fields.) I've found this similar question where it does happen when another one is created (Symfony CollectionType regards deletion+creation as a modification of an item), but that sort of drifted from the issue and there's no usable answer.

How do I make sure the form is updating the entities the user actually edited?

I already tried to render the Bs' IDs as a HiddenType, but then the form rightfully complains that the ID has no setter. It would probably force an ID on the wrong B anyways and Doctrine doesn't like that. I suppose I could add the Bs as unmapped and copy the values over to the correct objects manually, but that would defeat a good chunk of Symfony's form system.

I've used CollectionType before, but not for entities that are referenced elsewhere. I would then delete all of the previous entities and create the collection anew from the posted data. But I can't do that now, can I?

Upvotes: 1

Views: 1342

Answers (1)

msg
msg

Reputation: 8161

Since doctrine 2.1, it's possible to change how associations are indexed. This will allow you to use the id as the collection key (as the field has to be unique):

@OneToMany(targetEntity="B", mappedBy="A", indexBy="id")

You might also need to enable orphanRemoval so that the data is actually removed instead of the relation just set to null.

Upvotes: 4

Related Questions