Architecture¶
This chapter gives an overview of the overall architecture, terminology and constraints of Doctrine. It is recommended to read this chapter carefully.
Documents¶
A document is a lightweight, persistent domain object. A document can be any regular PHP class observing the following restrictions:
- A document class must not be final or contain final methods.
- All persistent properties/field of any document class should always be private or protected, otherwise lazy-loading might not work as expected.
- A document class must not implement
__clone
or do so safely. - A document class must not implement
__wakeup
or do so safely. Also consider implementing Serializable instead. - Any two document classes in a class hierarchy that inherit directly or indirectly from one another must not have a mapped property with the same name. That is, if B inherits from A then B must not have a mapped field with the same name as an already mapped field that is inherited from A.
Documents support inheritance, polymorphic associations, and polymorphic queries. Both abstract and concrete classes can be documents. Documents may extend non-document classes as well as document classes, and non-document classes may extend document classes.
Tip
The constructor of a document is only ever invoked when you construct a new instance with the new keyword. Doctrine never calls document constructors, thus you are free to use them as you wish and even have it require arguments of any type.
Document states¶
A document instance can be characterized as being NEW, MANAGED, DETACHED or REMOVED.
- A NEW document instance has no persistent identity, and is not yet associated with a DocumentManager and a UnitOfWork (i.e. those just created with the "new" operator).
- A MANAGED document instance is an instance with a persistent identity that is associated with a DocumentManager and whose persistence is thus managed.
- A DETACHED document instance is an instance with a persistent identity that is not (or no longer) associated with a DocumentManager and a UnitOfWork.
- A REMOVED document instance is an instance with a persistent identity, associated with a DocumentManager, that will be removed from the database upon transaction commit.
Persistent fields¶
The persistent state of a document is represented by instance variables. An instance variable must be directly accessed only from within the methods of the document by the document instance itself. Instance variables must not be accessed by clients of the document. The state of the document is available to clients only through the document's methods, i.e. accessor methods (getter/setter methods) or other business methods.
Collection-valued persistent fields and properties must be defined
in terms of the Doctrine\Common\Collections\Collection
interface. The collection implementation type may be used by the
application to initialize fields or properties before the document is
made persistent. Once the document becomes managed (or detached),
subsequent access must be through the interface type.
Serializing documents¶
Serializing documents can be problematic and is not really
recommended, at least not as long as a document instance still holds
references to proxy objects or is still managed by an
DocumentManager. If you intend to serialize (and unserialize) document
instances that still hold references to proxy objects you may run
into problems with private properties because of technical
limitations. Proxy objects implement __sleep
and it is not
possible for __sleep
to return names of private properties in
parent classes. On the other hand it is not a solution for proxy
objects to implement Serializable
because Serializable does not
work well with any potential cyclic object references (at least we
did not find a way yet, if you did, please contact us).
The DocumentManager¶
The DocumentManager
class is a central access point to the ODM
functionality provided by Doctrine. The DocumentManager
API is
used to manage the persistence of your objects and to query for
persistent objects.
Transactional write-behind¶
An DocumentManager
and the underlying UnitOfWork
employ a
strategy called "transactional write-behind" that delays the
execution of query statements in order to execute them in the most
efficient way and to execute them at the end of a transaction so
that all write locks are quickly released. You should see Doctrine
as a tool to synchronize your in-memory objects with the database
in well defined units of work. Work with your objects and modify
them as usual and when you're done call DocumentManager#flush()
to make your changes persistent.
The Unit of Work¶
Internally an DocumentManager
uses a UnitOfWork
, which is a
typical implementation of the
Unit of Work pattern,
to keep track of all the things that need to be done the next time
flush
is invoked. You usually do not directly interact with a
UnitOfWork
but with the DocumentManager
instead.