2
votes

Wow, this is very strange:

$bar = new Bar();

$foo = $entity->getFoo(); 
$bar->setFoo($foo);

$em->persist($bar); 
$em->flush();

and I obtain the following message

A new entity was found through the relationship [....]

By reading on the net, I undertand that if fetch two object from two different entity managers, one manager will doesn't know about entities fetched from other manager. Since here I'm into a "db hook" (postPersist) and I've manager injected from DIC, I've tried to change my code in agreement:

$bar = new Bar();

$foo_id = $entity->getFoo()->getId();
$foo = $em->getRepository('MyBundleName:Foo')->findOneBy(array('id'=>$foo_id));
$bar->setFoo($foo);

$em->persist($bar); 
$em->flush();

but nothing changed.

Can someone point me to right direction and, most important, explain what's going on here?


UPDATE

I've migrated all code outside db hooks and I've created a new service that will do pretty much same things of hooks but has to called explicitly after flush() Is very strange, however, that nothing changed. I've also tried to use spl_obj_hash onto entity manager for retrieve information about the entity manager who flush object into db and "other one" that will retrieve $foo from db and try to persist $bar. This is the result:

SPL_OBJ ENTITY MANAGER - 1: 0000000021770e03000000001eda54f7
SPL_OBJ ENTITY MANAGER - 2: 0000000021770e03000000001eda54f7

if I'm not wrong, they're the same entity manager object. I'm pretty confused actually...


UPDATE - WORKING CODE

I've found a "code combination" that will do the work but I'm still pretty confused about it.

If I use first snippet of code (where $foo is retrieved from $entity itself) and flush only $bar, error is still there.

If I use second snippet of code (where $foo is retrieved from entity manager) and persist only $bar, all works properly (obviosuly if I call $flush() without parameters, issue is still there)

5
Just to be clear: You are using 2 entity-managers? If so, how do you retrieve those entity-managers?Jasper N. Brouwer
@JasperN.Brouwer: No, I'm not using two entity managers as I inject them directly from DIC and as you can see, i used spl_obj_hash where I persist foo and where i retrieve it: they are the same entity managerDonCallisto
Ok, can you create a gist of the hook (so we can look at the code)?Jasper N. Brouwer
@A.L you're right, but, as a matter of fact, this is a very old post, I don't maintain that code anymore and last but not least, what I called "working solution" was not really a good one. This is the motivation behind no answer and only update in the question :)DonCallisto
@DonCallisto: Thank you for your response. I resolved the issue myself. Although the solution works good, I'm not really happy with how I resolved it. I will post it as a new question here and seek answers from the communityverisimilitude

5 Answers

6
votes

I had the same problem and resolved it, I'm posting it because I haven't seen it mentioned anywhere and it might help someone.

I have a service that parses data & persists it to entities, service to which I'm feeding the entityManager & child entities. And I started to have the same error on persist. Using merge() didn't help as it just threw me "A managed dirty+entity [...]" error instead.

After a little digging it seems that as far as Doctrine is concerned the entities I was feeding my service came from a different entityManager, so you actually have to get the entities from the entityManager inside the service if you are using it to persist.

1
votes

I fixed mine by removing clear

$this->getDoctrine()->getManager()->clear();

0
votes

I'm not sure since I never had this issue before and right now I'm not in the position to replicate it. But I will give you some options I would try:

If the two entitymanagers are using the same database you can merge (http://docs.doctrine-project.org/en/2.0.x/reference/working-with-objects.html#merging-entities) the entity into the other entitymanager. In this case that will look something like this:

$em->merge($foo);

This makes sure the entity $foo is managed by your entitymanager.

Also, remember that a postPersist is executed after the database operations. I think you have better chances if you try your modified code in a prepersist method.

As the documentation says:

prePersist  - The prePersist event occurs for a given entity before the respective
              EntityManager persist operation for that entity is executed.

postPersist - The postPersist event occurs for an entity after the entity has 
              been made persistent. It will be invoked after the database insert
              operations. Generated primary key values are available in the 
              postPersist event.

Full documentation can be found here: http://docs.doctrine-project.org/en/2.0.x/reference/events.html#lifecycle-events

Just try this and let me know the result

0
votes

Try : $em->merge($bar);

$bar = new Bar();

$foo = $entity->getFoo(); 
$bar->setFoo($foo);

$em->merge($bar); 
$em->flush();

[1] Doctrine - A new entity was found through the relationship

-4
votes

It's not so clear from your code, but I think you create a new $foo, but you don't save it before to save $bar. Try this:

$em->persist($foo); 
$em->flush();    
$bar->setFoo($foo);
$em->persist($bar); 
$em->flush();

In general you can escape this by using cascade=persist on the association of your entities.