Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Doctrine Cascade Options for OneToMany

I'm having a hard time making sense of the Doctrine manual's explanation of cascade operations and need someone to help me understand the options in terms of a simple ManyToOne relationship.

In my application, I have a table/entity named Article that has a foreign key field referencing the 'id' field in a table/entity named Topic.

When I create a new Article, I select the Topic from a dropdown menu. This inserts an integer into the 'topic_id' foreign key field in the Article table.

I have the $topic association set up in the Article entity like this:

/**  * @ManyToOne(targetEntity="Topic")  * @JoinColumn(name="topic_id", referencedColumnName="id", nullable=false)  */ private $topic; 

The Topic entity doesn't have any reciprocating annotation regarding the Article entity. Topics don't care what Articles reference them and nothing needs to happen to a Topic when an Article that references the Topic is deleted.

Because I'm not specifying the cascade operation in the Article entity, Doctrine throws an error when I try to create a new Article: "A new entity was found through a relationship that was not configured to cascade persist operations. Explicitly persist the new entity or configure cascading persist operations on the relationship."

So I know I need to choose a cascade operation to include in the Article entity, but how do I know which operation to choose in this situation?

From reading the Doctrine manual, "detach" sounds like the right option. But researching others' similar questions here and here makes me think I want to use "persist" instead.

Can anyone help me understand what "persist," "remove," "merge," and "detach" mean in terms of a simple ManyToOne relationship like the one I've described?

like image 454
cantera Avatar asked Oct 10 '11 06:10

cantera


1 Answers

In the Doctrine2 documentation "9.6. Transitive persistence / Cascade Operations" there are few examples of how you should configure your entities so that when you persist $article, the $topic would be also persisted. In your case I'd suggest this annotation for Topic entity:

/**  * @OneToMany(targetEntity="Article", mappedBy="topic", cascade={"persist", "remove"})  */  private $articles;   

The drawback of this solution is that you have to include $articles collection to Topic entity, but you can leave it private without getter/setter.

And as @kurt-krueckeberg mentioned, you must pass the real Topic entity when creating new Article, i.e.:

$topic = $em->getRepository('Entity\Topic')->find($id); $article = new Article($topic); $em->persist($article); $em->flush();  // perhaps, in this case you don't even need to configure cascade operations 

Good luck!

like image 129
Sergiy Sokolenko Avatar answered Oct 02 '22 02:10

Sergiy Sokolenko