I noticed that every time i talk with a college about doctrine events there is confusion about which event does what. So I tried to lay it out here.
You can look at the official documentation for the newest info but here is the list of doctrine events in the order they are called.
All events are triggered in the $em->flush();
method in this order.
Or even more precisely in Doctrine\ORM\UnitOfWork::commit
method.
Take a look there if you really want to know what you are doing.
- preFlush is called first, directly after the
flush
invoke. - now the changeset aka unitOfWork is computed, doctrine does not know what has changed before this point.
- onFlush is called next, directly after the changeset is computed. If you change anything here, you’ll have to deal with the unitOfWork manually.
- now the database transaction is started and doctrine goes through all entities individually, you should not add entities after this point.
- preUpdate is called here but only if an entity has been persisted before and changed. You can still change the entity here. Note that prePersist and preRemove are not called here, more on that later. Doctrine does recompute the changeset automatically if this event is used at all, so they expect you to make changes here.
- the single insert/update/delete query is executed
- postPersist, postUpdate, postRemove are called. You rarely want to use this event.
- now the transaction is commited to the database which may or may not succeed
- postFlush is now called. You can’t change anything anymore since the transaction is now done, but this is an ideal point at which to send emails for example. The unitOfWork is not yet reset so you can still see what happened.
Knowing this now, the 2 events you are probably most interested in are onFlush and postFlush. All other events have only very specific use cases.
what about prePersist and preDelete events?
prePersist and preRemove are called during $em->persist()
and $em->remove()
respectively if they are explicitly called with that entity.
This makes these events really awkward to deal with since they could be called during flush (though cascade while computing the change set)
but also before the entity is even fully filled. Think of this situation:
$entity = new Entity();
$em->persist($entity); // calls prePersist
$entity->setName("example"); // this name was not known in pre persist
Even stranger, you can call the prePersist event multiple times