Your problem is with calling $em->persist($article); before changing ClassMetadata .
When a new UnitOfWork object is UnitOfWork , an id is created using ArticleNumberGenerator and stored in the entityIdentifiers field. ManyToManyPersister uses this value with the PersistentCollection when populating the row of the relationship table.
When flush called, UoW computes the set of changes to the object and stores the actual value of the identifier - therefore, you get the correct data after you join the association with the addition of the association. But it does not update entityIdentifiers data.
To fix this, you can simply move persist to modify the ClassMetadata object. But the path still looks like a hack. IMO, a more optimal way is to create a custom generator that will use the assigned identifier, if provided or to generate a new one.
PS . Another thing to keep in mind is that your generation identifier path is unsafe, it will produce duplicate identifiers at high load.
UPD I UoW that UoW does not use idGeneratorType (it is used by factory metadata to set the correct idGenerator value), so you must set the correct idGenerator
public function createHandmadeAction($handmade) { $tag = new Tag(); $tag->setName('Tag ' . rand(1, 99)); $article = new Article(); $article->setTitle('Test article ' . rand(1, 999)); $article->getTags()->add($tag); $em = $this->getDoctrine()->getManager(); $em->getConnection()->beginTransaction(); $metadata = $em->getClassMetadata(get_class($article)); $metadata->setIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_NONE); $metadata->setIdGenerator(new \Doctrine\ORM\Id\AssignedGenerator()); $article->setId($handmade); $em->persist($article); try { $em->flush(); $em->getConnection()->commit(); } catch (\RuntimeException $e) { $em->getConnection()->rollBack(); throw $e; } return new Response('Created article id ' . $article->getId() . '.'); }
This works as expected.
origaminal Aug 05 '15 at 14:34 2015-08-05 14:34
source share