2010-11-02 00:03:50 +03:00
|
|
|
|
Architecture
|
|
|
|
|
============
|
|
|
|
|
|
2010-11-01 23:16:12 +03:00
|
|
|
|
This chapter gives an overview of the overall architecture,
|
|
|
|
|
terminology and constraints of Doctrine 2. It is recommended to
|
|
|
|
|
read this chapter carefully.
|
|
|
|
|
|
|
|
|
|
Entities
|
|
|
|
|
--------
|
|
|
|
|
|
|
|
|
|
An entity is a lightweight, persistent domain object. An entity can
|
|
|
|
|
be any regular PHP class observing the following restrictions:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- An entity class must not be final or contain final methods.
|
|
|
|
|
- All persistent properties/field of any entity class should
|
|
|
|
|
always be private or protected, otherwise lazy-loading might not
|
|
|
|
|
work as expected.
|
|
|
|
|
- An entity class must not implement ``__clone`` or
|
|
|
|
|
`do so safely <http://www.doctrine-project.org/documentation/cookbook/2_0/en/implementing-wakeup-or-clone>`_.
|
|
|
|
|
- An entity class must not implement ``__wakeup`` or
|
|
|
|
|
`do so safely <http://www.doctrine-project.org/documentation/cookbook/2_0/en/implementing-wakeup-or-clone>`_.
|
|
|
|
|
Also consider implementing
|
|
|
|
|
`Serializable <http://de3.php.net/manual/en/class.serializable.php]>`_
|
|
|
|
|
instead.
|
|
|
|
|
- Any two entity 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.
|
|
|
|
|
|
|
|
|
|
Entities support inheritance, polymorphic associations, and
|
|
|
|
|
polymorphic queries. Both abstract and concrete classes can be
|
|
|
|
|
entities. Entities may extend non-entity classes as well as entity
|
|
|
|
|
classes, and non-entity classes may extend entity classes.
|
|
|
|
|
|
|
|
|
|
**TIP** The constructor of an entity is only ever invoked when
|
|
|
|
|
*you* construct a new instance with the *new* keyword. Doctrine
|
|
|
|
|
never calls entity constructors, thus you are free to use them as
|
|
|
|
|
you wish and even have it require arguments of any type.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Entity states
|
|
|
|
|
~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
|
|
An entity instance can be characterized as being NEW, MANAGED,
|
|
|
|
|
DETACHED or REMOVED.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- A NEW entity instance has no persistent identity, and is not yet
|
|
|
|
|
associated with an EntityManager and a UnitOfWork (i.e. those just
|
|
|
|
|
created with the "new" operator).
|
|
|
|
|
- A MANAGED entity instance is an instance with a persistent
|
|
|
|
|
identity that is associated with an EntityManager and whose
|
|
|
|
|
persistence is thus managed.
|
|
|
|
|
- A DETACHED entity instance is an instance with a persistent
|
|
|
|
|
identity that is not (or no longer) associated with an
|
|
|
|
|
EntityManager and a UnitOfWork.
|
|
|
|
|
- A REMOVED entity instance is an instance with a persistent
|
|
|
|
|
identity, associated with an EntityManager, that will be removed
|
|
|
|
|
from the database upon transaction commit.
|
|
|
|
|
|
|
|
|
|
Persistent fields
|
|
|
|
|
~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
|
|
The persistent state of an entity is represented by instance
|
|
|
|
|
variables. An instance variable must be directly accessed only from
|
|
|
|
|
within the methods of the entity by the entity instance itself.
|
|
|
|
|
Instance variables must not be accessed by clients of the entity.
|
|
|
|
|
The state of the entity is available to clients only through the
|
|
|
|
|
entity’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 entity is
|
|
|
|
|
made persistent. Once the entity becomes managed (or detached),
|
|
|
|
|
subsequent access must be through the interface type.
|
|
|
|
|
|
|
|
|
|
Serializing entities
|
|
|
|
|
~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
|
|
Serializing entities can be problematic and is not really
|
|
|
|
|
recommended, at least not as long as an entity instance still holds
|
|
|
|
|
references to proxy objects or is still managed by an
|
|
|
|
|
EntityManager. If you intend to serialize (and unserialize) entity
|
|
|
|
|
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 EntityManager
|
|
|
|
|
-----------------
|
|
|
|
|
|
|
|
|
|
The ``EntityManager`` class is a central access point to the ORM
|
|
|
|
|
functionality provided by Doctrine 2. The ``EntityManager`` API is
|
|
|
|
|
used to manage the persistence of your objects and to query for
|
|
|
|
|
persistent objects.
|
|
|
|
|
|
|
|
|
|
Transactional write-behind
|
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
|
|
An ``EntityManager`` and the underlying ``UnitOfWork`` employ a
|
|
|
|
|
strategy called "transactional write-behind" that delays the
|
|
|
|
|
execution of SQL 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 ``EntityManager#flush()``
|
|
|
|
|
to make your changes persistent.
|
|
|
|
|
|
|
|
|
|
The Unit of Work
|
|
|
|
|
~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
|
|
Internally an ``EntityManager`` 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 ``EntityManager`` instead.
|
|
|
|
|
|
|
|
|
|
|