125 lines
5.3 KiB
Plaintext
125 lines
5.3 KiB
Plaintext
|
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
|
||
|
:doc:`do so safely <../cookbook/implementing-wakeup-or-clone>`.
|
||
|
- A document class must not implement ``__wakeup`` or
|
||
|
:doc:`do so safely <../cookbook/implementing-wakeup-or-clone>`.
|
||
|
Also consider implementing
|
||
|
`Serializable <http://de3.php.net/manual/en/class.serializable.php>`_
|
||
|
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 <http://martinfowler.com/eaaCatalog/unitOfWork.html>`_,
|
||
|
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.
|