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?
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!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With