In Symfony2, if I embed a collection of forms pointing at a many to one relationship in Doctrine and allow adding and deletion, if I delete a record from the beginning, add one
One way to pass primary id is to use INDEX BY.
For example, say I have an entity called Customer and a Customer has several Emails. In my Customer repository class, I can specify my collection to be indexed by Email's primary id.
$qb->select('c, e')
->leftJoin('c.emails', 'e', null, null, 'e.id')
->where('c.id = :id');
By doing so, the generated name of the input tag would be
customer[emails][e.id][fieldName]
Upon submitting the form, Symfony will bind the request values according to the input names.
Based on the Akkumulator's answer and comment and some experimentation, I did this:
Create new fields (using Javascript as described in the documentation) with __name__
replaced not by a number but by a string: new_ followed by an forever increasing number that has nothing to do with the list (e.g. new_1, new_2, new_3...)
I don't have to push the primary keys into the forms and I don't need indexBy either - that's good, because indexBy felt like it was too far removed from the form, ending in having the Action at a distance anti-pattern.
Why this works:
If you want to index the collection (by the entity id) for all querys, you can simply use the indexBy
annotation in your entity class.
/**
* @ORM\OneToMany(targetEntity="EntityClass", mappedBy="EntityVariable", indexBy="id")
*/
private $collection;