I tried to gather some information about the following way to delete automatically child entity when a parent entity is deleted. Seems that the most common way is to use one those three annotation: cascade={"remove"}
OR orphanRemoval=true
OR ondelete="CASCADE"
.
I am a bit confused about the third one: ondelete="CASCADE"
, as the explanation in doctrine official documentation about this one are very scarce) and I would love if someone could confirm me the following information I gathered and understand from my research on the net and experience…
What does it do?
cascade={"remove"}
==> the entity on the inverse side is deleted when the owning side entity is. Even if you are in a ManyToMany
with other owning side entity.
- should be used on collection (so in
OneToMany
orManyToMany
relationship) - implementation in the ORM
orphanRemoval=true
==> the entity on the inverse side is deleted when the owning side entity is AND it is not connected to any other owning side entity anymore. (ref. doctrine official_doc
- implementation in the ORM
- can be used with
OneToOne
,OneToMany
orManyToMany
onDelete="CASCADE"
==> this will add On Delete Cascade to the foreign key column in the database
- This strategy is a bit tricky to get right but can be very powerful and fast. (ref. doctrine official_doc … but haven't read more explanations)
- ORM has to do less work (compared to the two previous ways of doing it) and therefore should have better performance.
other information
- all those 3 ways of doing are implemented on bidirectional relationship entities (right???)
- using
cascade={"remove"}
completely by-passes any foreign key onDelete=CASCADE. (ref. doctrine_official_doc)
EXAMPLE ON HOW TO USE IT IN CODE
orphanRemoval
andcascade={"remove"}
are defined in the inversed entity class.ondelete="CASCADE"
is defined in the owner entity- you can also just write
@ORM\JoinColumn(onDelete="CASCADE")
and let doctrine handle the column names
cascade={"remove"}
/**
* @OneToMany(targetEntity="Phonenumber", mappedBy="contact", cascade={"remove"})
*/
protected $Phonenumbers
orphanRemoval=true
/**
* @OneToMany(targetEntity="Phonenumber", mappedBy="contact", orphanRemoval=true)
*/
protected $Phonenumbers
onDelete="CASCADE"
/**
* @ManyToOne(targetEntity="Contact", inversedBy="phonenumbers")
* @JoinColumn(name="contact_id", referencedColumnName="contact_id", onDelete="CASCADE")
*/
protected $contact;
Best Answer
onDelete="CASCADE"
is managed by the database itself.cascade={"remove"}
is managed by doctrine.onDelete="CASCADE"
is faster because the operations are performed on database level instead by doctrine. The removing is performed by the database server and not Doctrine. Withcascade={"remove"}
doctrine has to manage the entity itself and will perform extra checks to see if it doesn't have any other owning entities. When no other exists it will delete the entity. But this creates overhead.cascade={"remove"}
orphanRemoval="true"
onDelete="CASCADE"