This document discusses key concepts and components in the Doctrine ORM, including:
- The EntityManager acts as the central access point and manages entity persistence. It allows persisting, flushing, merging, detaching, removing, and refreshing entities.
- The UnitOfWork maintains a list of entities affected by a transaction and coordinates writing changes to the database. It tracks entity states and maintains an identity map.
- Persisters handle writing entity and collection data while events allow reacting to state changes at specific points in the persistence process.
3. What is The Doctrine Project?
Annotations
Cache
Coding Standard
Collections
Common
Database Abstraction Layer
Event Manager
Inflector
Instantiator
Lexer
The Doctrine Project is the home to several PHP libraries primarily focused on database storage and object
mapping.
Migrations
MongoDB Abstraction Layer
MongoDB Object Document Mapper
Object Relational Mapper
Persistence
PHPCR ODM
Reflection
RST Parser
Skeleton Mapper
4. Doctrine ORM
PHP object relational mapper (ORM) that sits on top of a powerful database abstraction layer (DBAL).
https://martinfowler.com/eaaCatalog/dataMapper.html
The Data Mapper is a layer of software that separates the in-memory objects from the database. Its responsibility is to transfer data
between the two and also to isolate them from each other. With Data Mapper the in-memory objects needn't know even that there's a
database present; they need no SQL interface code, and certainly no knowledge of the database schema.
5. Entity Manager
- persist
- flush
- merge
- detach
- remove
- refresh
- clear
- ...
- persist
- commit
- merge
- detach
- remove
- refresh
- clear
- ...
The EntityManager is the central access point to ORM functionality. It is a facade to all different ORM
subsystems such as UnitOfWork, Query Language and Repository API.
EntityManager UnitOfWork
6. EntityManager::persist
Tells the EntityManager to make an instance managed and persistent.
persist() methods is not so smart as a lot of developers think.
This method:
1. Checks that doctrine has metadata for this entity
2. If this entity doesn’t have filled id (in most cases) - mark it with state=STATE_NEW
3. Call prePersist event
4. Generate id (if possible)
5. Schedule this entity for inserting
(!) This method doesn’t construct SQL for insert.
7. EntityManager::flush
Flushes all changes to objects that have been queued up to now to the database. This effectively
synchronizes the in-memory state of managed objects with the database.
This method:
1. Dispatches preFlush event
2. Calculates change set based on scheduled (for insert/delete/etc) entities.
3. Dispatch onFlush
4. Start transaction
5. Execute inserts, updates, extra updates
6. Collection deletes
7. Collection updates (delete/update/insert row)
8. Execute deletions
9. Dispatch postFlush
10. Clear up internal state
8. EntityManager::close
Closes the EntityManager. All entities that are currently managed by this EntityManager become detached.
The EntityManager may no longer be used after it is closed.
Exception “The EntityManager is closed.” will thrown in case of using EM after closing it.
EM can be closed manually by calling close() method or in case of error during the transaction process in
UnitOfWork::commit()
$em->close();
9. EntityManager::merge
Merges the state of a detached entity into the persistence context of this EntityManager and returns the
managed copy of the entity. The entity passed to merge will not become associated/managed with this
EntityManager.
You should use result of this call in your code:
$managedEntity = $em->merge($detachedEntity);
11. EntityManager::remove
Removes an entity instance.
A removed entity will be removed from the database at or before transaction commit or as a result of the flush
operation.
$em->remove($entity);
14. UnitOfWork
UnitOfWork class implements UnitOfWork pattern.
This class responsible for maintaining a list of objects affected by a business transaction and coordinates the writing out of
changes and the resolution of concurrency problems.
https://martinfowler.com/eaaCatalog/unitOfWork.html
16. UnitOfWork states
STATE_MANAGED - Persisted entity, UoW tracks state of this entity
STATE_NEW - New entity and is not managed by EntityManager yet.
STATE_DETACHED - Persisted entity (with identifier), but EntityManager doesn’t track changes
STATE_REMOVED - Persisted entity but scheduled for removing
17. UnitOfWork Identity Map
The identity map that holds references to all managed entities that have an identity.
The entities are grouped by their class name.
Since all classes in a hierarchy must share the same identifier set, we always take the root class
name of the hierarchy.
18. UnitOfWork Original Entity Data
Map of the original entity data of managed entities
Keys are object ids (spl_object_hash).
This is used for calculating changesets at commit time.
21. Bonus: extra updates (internal)
UnitOfWork::scheduleExtraUpadate
Schedules an extra update that will be executed immediately after the regular entity updates within
the currently running commit cycle.
Can be used to add additional updates during lifecycle events.
For example in postPersist or postUpdate
$uow->scheduleExtraUpdate($entity, ['entityId' => [null, $id]]);