Start reorganizing documentation with focus on simplicity.
This commit is contained in:
parent
6ee9e2284a
commit
e0d706219b
@ -25,22 +25,15 @@ of contents <toc>`.
|
|||||||
Getting Started
|
Getting Started
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
* **Setup**:
|
||||||
|
:doc:`Installation & Configuration <reference/configuration>` |
|
||||||
|
:doc:`Commandline Tools <reference/tools>`
|
||||||
|
|
||||||
* **Tutorial**:
|
* **Tutorial**:
|
||||||
:doc:`Code First <tutorials/getting-started>` |
|
:doc:`Code First <tutorials/getting-started>` |
|
||||||
:doc:`Model First <tutorials/getting-started-models>` |
|
:doc:`Model First <tutorials/getting-started-models>` |
|
||||||
:doc:`Database First <tutorials/getting-started-database>`
|
:doc:`Database First <tutorials/getting-started-database>`
|
||||||
|
|
||||||
* **Introduction**:
|
|
||||||
:doc:`In 10 quick steps <tutorials/in-ten-quick-steps>` |
|
|
||||||
:doc:`Architecture <reference/architecture>`
|
|
||||||
|
|
||||||
* **Setup**:
|
|
||||||
:doc:`Installation <reference/installation>` |
|
|
||||||
:doc:`Configuration <reference/configuration>` |
|
|
||||||
:doc:`Tools <reference/tools>`
|
|
||||||
|
|
||||||
* :doc:`Limitations and knowns issues <reference/limitations-and-known-issues>`
|
|
||||||
|
|
||||||
Mapping Objects onto a Database
|
Mapping Objects onto a Database
|
||||||
-------------------------------
|
-------------------------------
|
||||||
|
|
||||||
@ -75,6 +68,9 @@ Working with Objects
|
|||||||
Advanced Topics
|
Advanced Topics
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
* :doc:`Architecture <reference/architecture>`
|
||||||
|
* :doc:`Advanced Configuration <reference/advanced-configuration>`
|
||||||
|
* :doc:`Limitations and knowns issues <reference/limitations-and-known-issues>`
|
||||||
* :doc:`Transactions and Concurrency <reference/transactions-and-concurrency>`
|
* :doc:`Transactions and Concurrency <reference/transactions-and-concurrency>`
|
||||||
* :doc:`Filters <reference/filters>`
|
* :doc:`Filters <reference/filters>`
|
||||||
* :doc:`NamingStrategy <reference/namingstrategy>`
|
* :doc:`NamingStrategy <reference/namingstrategy>`
|
||||||
|
432
docs/en/reference/advanced-configuration.rst
Normal file
432
docs/en/reference/advanced-configuration.rst
Normal file
@ -0,0 +1,432 @@
|
|||||||
|
Advanced Configuration
|
||||||
|
======================
|
||||||
|
|
||||||
|
The configuration of the EntityManager requires a
|
||||||
|
``Doctrine\ORM\Configuration`` instance as well as some database
|
||||||
|
connection parameters. This example shows all the potential
|
||||||
|
steps of configuration.
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
|
||||||
|
<?php
|
||||||
|
use Doctrine\ORM\EntityManager,
|
||||||
|
Doctrine\ORM\Configuration;
|
||||||
|
|
||||||
|
// ...
|
||||||
|
|
||||||
|
if ($applicationMode == "development") {
|
||||||
|
$cache = new \Doctrine\Common\Cache\ArrayCache;
|
||||||
|
} else {
|
||||||
|
$cache = new \Doctrine\Common\Cache\ApcCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
$config = new Configuration;
|
||||||
|
$config->setMetadataCacheImpl($cache);
|
||||||
|
$driverImpl = $config->newDefaultAnnotationDriver('/path/to/lib/MyProject/Entities');
|
||||||
|
$config->setMetadataDriverImpl($driverImpl);
|
||||||
|
$config->setQueryCacheImpl($cache);
|
||||||
|
$config->setProxyDir('/path/to/myproject/lib/MyProject/Proxies');
|
||||||
|
$config->setProxyNamespace('MyProject\Proxies');
|
||||||
|
|
||||||
|
if ($applicationMode == "development") {
|
||||||
|
$config->setAutoGenerateProxyClasses(true);
|
||||||
|
} else {
|
||||||
|
$config->setAutoGenerateProxyClasses(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
$connectionOptions = array(
|
||||||
|
'driver' => 'pdo_sqlite',
|
||||||
|
'path' => 'database.sqlite'
|
||||||
|
);
|
||||||
|
|
||||||
|
$em = EntityManager::create($connectionOptions, $config);
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Do not use Doctrine without a metadata and query cache!
|
||||||
|
Doctrine is optimized for working with caches. The main
|
||||||
|
parts in Doctrine that are optimized for caching are the metadata
|
||||||
|
mapping information with the metadata cache and the DQL to SQL
|
||||||
|
conversions with the query cache. These 2 caches require only an
|
||||||
|
absolute minimum of memory yet they heavily improve the runtime
|
||||||
|
performance of Doctrine. The recommended cache driver to use with
|
||||||
|
Doctrine is `APC <http://www.php.net/apc>`_. APC provides you with
|
||||||
|
an opcode-cache (which is highly recommended anyway) and a very
|
||||||
|
fast in-memory cache storage that you can use for the metadata and
|
||||||
|
query caches as seen in the previous code snippet.
|
||||||
|
|
||||||
|
Configuration Options
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
The following sections describe all the configuration options
|
||||||
|
available on a ``Doctrine\ORM\Configuration`` instance.
|
||||||
|
|
||||||
|
Proxy Directory (***REQUIRED***)
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
|
||||||
|
<?php
|
||||||
|
$config->setProxyDir($dir);
|
||||||
|
$config->getProxyDir();
|
||||||
|
|
||||||
|
Gets or sets the directory where Doctrine generates any proxy
|
||||||
|
classes. For a detailed explanation on proxy classes and how they
|
||||||
|
are used in Doctrine, refer to the "Proxy Objects" section further
|
||||||
|
down.
|
||||||
|
|
||||||
|
Proxy Namespace (***REQUIRED***)
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
|
||||||
|
<?php
|
||||||
|
$config->setProxyNamespace($namespace);
|
||||||
|
$config->getProxyNamespace();
|
||||||
|
|
||||||
|
Gets or sets the namespace to use for generated proxy classes. For
|
||||||
|
a detailed explanation on proxy classes and how they are used in
|
||||||
|
Doctrine, refer to the "Proxy Objects" section further down.
|
||||||
|
|
||||||
|
Metadata Driver (***REQUIRED***)
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
|
||||||
|
<?php
|
||||||
|
$config->setMetadataDriverImpl($driver);
|
||||||
|
$config->getMetadataDriverImpl();
|
||||||
|
|
||||||
|
Gets or sets the metadata driver implementation that is used by
|
||||||
|
Doctrine to acquire the object-relational metadata for your
|
||||||
|
classes.
|
||||||
|
|
||||||
|
There are currently 4 available implementations:
|
||||||
|
|
||||||
|
|
||||||
|
- ``Doctrine\ORM\Mapping\Driver\AnnotationDriver``
|
||||||
|
- ``Doctrine\ORM\Mapping\Driver\XmlDriver``
|
||||||
|
- ``Doctrine\ORM\Mapping\Driver\YamlDriver``
|
||||||
|
- ``Doctrine\ORM\Mapping\Driver\DriverChain``
|
||||||
|
|
||||||
|
Throughout the most part of this manual the AnnotationDriver is
|
||||||
|
used in the examples. For information on the usage of the XmlDriver
|
||||||
|
or YamlDriver please refer to the dedicated chapters
|
||||||
|
``XML Mapping`` and ``YAML Mapping``.
|
||||||
|
|
||||||
|
The annotation driver can be configured with a factory method on
|
||||||
|
the ``Doctrine\ORM\Configuration``:
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
|
||||||
|
<?php
|
||||||
|
$driverImpl = $config->newDefaultAnnotationDriver('/path/to/lib/MyProject/Entities');
|
||||||
|
$config->setMetadataDriverImpl($driverImpl);
|
||||||
|
|
||||||
|
The path information to the entities is required for the annotation
|
||||||
|
driver, because otherwise mass-operations on all entities through
|
||||||
|
the console could not work correctly. All of metadata drivers
|
||||||
|
accept either a single directory as a string or an array of
|
||||||
|
directories. With this feature a single driver can support multiple
|
||||||
|
directories of Entities.
|
||||||
|
|
||||||
|
Metadata Cache (***RECOMMENDED***)
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
|
||||||
|
<?php
|
||||||
|
$config->setMetadataCacheImpl($cache);
|
||||||
|
$config->getMetadataCacheImpl();
|
||||||
|
|
||||||
|
Gets or sets the cache implementation to use for caching metadata
|
||||||
|
information, that is, all the information you supply via
|
||||||
|
annotations, xml or yaml, so that they do not need to be parsed and
|
||||||
|
loaded from scratch on every single request which is a waste of
|
||||||
|
resources. The cache implementation must implement the
|
||||||
|
``Doctrine\Common\Cache\Cache`` interface.
|
||||||
|
|
||||||
|
Usage of a metadata cache is highly recommended.
|
||||||
|
|
||||||
|
The recommended implementations for production are:
|
||||||
|
|
||||||
|
|
||||||
|
- ``Doctrine\Common\Cache\ApcCache``
|
||||||
|
- ``Doctrine\Common\Cache\MemcacheCache``
|
||||||
|
- ``Doctrine\Common\Cache\XcacheCache``
|
||||||
|
- ``Doctrine\Common\Cache\RedisCache``
|
||||||
|
|
||||||
|
For development you should use the
|
||||||
|
``Doctrine\Common\Cache\ArrayCache`` which only caches data on a
|
||||||
|
per-request basis.
|
||||||
|
|
||||||
|
Query Cache (***RECOMMENDED***)
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
|
||||||
|
<?php
|
||||||
|
$config->setQueryCacheImpl($cache);
|
||||||
|
$config->getQueryCacheImpl();
|
||||||
|
|
||||||
|
Gets or sets the cache implementation to use for caching DQL
|
||||||
|
queries, that is, the result of a DQL parsing process that includes
|
||||||
|
the final SQL as well as meta information about how to process the
|
||||||
|
SQL result set of a query. Note that the query cache does not
|
||||||
|
affect query results. You do not get stale data. This is a pure
|
||||||
|
optimization cache without any negative side-effects (except some
|
||||||
|
minimal memory usage in your cache).
|
||||||
|
|
||||||
|
Usage of a query cache is highly recommended.
|
||||||
|
|
||||||
|
The recommended implementations for production are:
|
||||||
|
|
||||||
|
|
||||||
|
- ``Doctrine\Common\Cache\ApcCache``
|
||||||
|
- ``Doctrine\Common\Cache\MemcacheCache``
|
||||||
|
- ``Doctrine\Common\Cache\XcacheCache``
|
||||||
|
- ``Doctrine\Common\Cache\RedisCache``
|
||||||
|
|
||||||
|
For development you should use the
|
||||||
|
``Doctrine\Common\Cache\ArrayCache`` which only caches data on a
|
||||||
|
per-request basis.
|
||||||
|
|
||||||
|
SQL Logger (***Optional***)
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
|
||||||
|
<?php
|
||||||
|
$config->setSQLLogger($logger);
|
||||||
|
$config->getSQLLogger();
|
||||||
|
|
||||||
|
Gets or sets the logger to use for logging all SQL statements
|
||||||
|
executed by Doctrine. The logger class must implement the
|
||||||
|
``Doctrine\DBAL\Logging\SQLLogger`` interface. A simple default
|
||||||
|
implementation that logs to the standard output using ``echo`` and
|
||||||
|
``var_dump`` can be found at
|
||||||
|
``Doctrine\DBAL\Logging\EchoSQLLogger``.
|
||||||
|
|
||||||
|
Auto-generating Proxy Classes (***OPTIONAL***)
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
|
||||||
|
<?php
|
||||||
|
$config->setAutoGenerateProxyClasses($bool);
|
||||||
|
$config->getAutoGenerateProxyClasses();
|
||||||
|
|
||||||
|
Gets or sets whether proxy classes should be generated
|
||||||
|
automatically at runtime by Doctrine. If set to ``FALSE``, proxy
|
||||||
|
classes must be generated manually through the doctrine command
|
||||||
|
line task ``generate-proxies``. The strongly recommended value for
|
||||||
|
a production environment is ``FALSE``.
|
||||||
|
|
||||||
|
Development vs Production Configuration
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
You should code your Doctrine2 bootstrapping with two different
|
||||||
|
runtime models in mind. There are some serious benefits of using
|
||||||
|
APC or Memcache in production. In development however this will
|
||||||
|
frequently give you fatal errors, when you change your entities and
|
||||||
|
the cache still keeps the outdated metadata. That is why we
|
||||||
|
recommend the ``ArrayCache`` for development.
|
||||||
|
|
||||||
|
Furthermore you should have the Auto-generating Proxy Classes
|
||||||
|
option to true in development and to false in production. If this
|
||||||
|
option is set to ``TRUE`` it can seriously hurt your script
|
||||||
|
performance if several proxy classes are re-generated during script
|
||||||
|
execution. Filesystem calls of that magnitude can even slower than
|
||||||
|
all the database queries Doctrine issues. Additionally writing a
|
||||||
|
proxy sets an exclusive file lock which can cause serious
|
||||||
|
performance bottlenecks in systems with regular concurrent
|
||||||
|
requests.
|
||||||
|
|
||||||
|
Connection Options
|
||||||
|
------------------
|
||||||
|
|
||||||
|
The ``$connectionOptions`` passed as the first argument to
|
||||||
|
``EntityManager::create()`` has to be either an array or an
|
||||||
|
instance of ``Doctrine\DBAL\Connection``. If an array is passed it
|
||||||
|
is directly passed along to the DBAL Factory
|
||||||
|
``Doctrine\DBAL\DriverManager::getConnection()``. The DBAL
|
||||||
|
configuration is explained in the
|
||||||
|
`DBAL section <./../../../../../dbal/2.0/docs/reference/configuration/en>`_.
|
||||||
|
|
||||||
|
Proxy Objects
|
||||||
|
-------------
|
||||||
|
|
||||||
|
A proxy object is an object that is put in place or used instead of
|
||||||
|
the "real" object. A proxy object can add behavior to the object
|
||||||
|
being proxied without that object being aware of it. In Doctrine 2,
|
||||||
|
proxy objects are used to realize several features but mainly for
|
||||||
|
transparent lazy-loading.
|
||||||
|
|
||||||
|
Proxy objects with their lazy-loading facilities help to keep the
|
||||||
|
subset of objects that are already in memory connected to the rest
|
||||||
|
of the objects. This is an essential property as without it there
|
||||||
|
would always be fragile partial objects at the outer edges of your
|
||||||
|
object graph.
|
||||||
|
|
||||||
|
Doctrine 2 implements a variant of the proxy pattern where it
|
||||||
|
generates classes that extend your entity classes and adds
|
||||||
|
lazy-loading capabilities to them. Doctrine can then give you an
|
||||||
|
instance of such a proxy class whenever you request an object of
|
||||||
|
the class being proxied. This happens in two situations:
|
||||||
|
|
||||||
|
Reference Proxies
|
||||||
|
~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
The method ``EntityManager#getReference($entityName, $identifier)``
|
||||||
|
lets you obtain a reference to an entity for which the identifier
|
||||||
|
is known, without loading that entity from the database. This is
|
||||||
|
useful, for example, as a performance enhancement, when you want to
|
||||||
|
establish an association to an entity for which you have the
|
||||||
|
identifier. You could simply do this:
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
|
||||||
|
<?php
|
||||||
|
// $em instanceof EntityManager, $cart instanceof MyProject\Model\Cart
|
||||||
|
// $itemId comes from somewhere, probably a request parameter
|
||||||
|
$item = $em->getReference('MyProject\Model\Item', $itemId);
|
||||||
|
$cart->addItem($item);
|
||||||
|
|
||||||
|
Here, we added an Item to a Cart without loading the Item from the
|
||||||
|
database. If you invoke any method on the Item instance, it would
|
||||||
|
fully initialize its state transparently from the database. Here
|
||||||
|
$item is actually an instance of the proxy class that was generated
|
||||||
|
for the Item class but your code does not need to care. In fact it
|
||||||
|
**should not care**. Proxy objects should be transparent to your
|
||||||
|
code.
|
||||||
|
|
||||||
|
Association proxies
|
||||||
|
~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
The second most important situation where Doctrine uses proxy
|
||||||
|
objects is when querying for objects. Whenever you query for an
|
||||||
|
object that has a single-valued association to another object that
|
||||||
|
is configured LAZY, without joining that association in the same
|
||||||
|
query, Doctrine puts proxy objects in place where normally the
|
||||||
|
associated object would be. Just like other proxies it will
|
||||||
|
transparently initialize itself on first access.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Joining an association in a DQL or native query
|
||||||
|
essentially means eager loading of that association in that query.
|
||||||
|
This will override the 'fetch' option specified in the mapping for
|
||||||
|
that association, but only for that query.
|
||||||
|
|
||||||
|
|
||||||
|
Generating Proxy classes
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Proxy classes can either be generated manually through the Doctrine
|
||||||
|
Console or automatically by Doctrine. The configuration option that
|
||||||
|
controls this behavior is:
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
|
||||||
|
<?php
|
||||||
|
$config->setAutoGenerateProxyClasses($bool);
|
||||||
|
$config->getAutoGenerateProxyClasses();
|
||||||
|
|
||||||
|
The default value is ``TRUE`` for convenient development. However,
|
||||||
|
this setting is not optimal for performance and therefore not
|
||||||
|
recommended for a production environment. To eliminate the overhead
|
||||||
|
of proxy class generation during runtime, set this configuration
|
||||||
|
option to ``FALSE``. When you do this in a development environment,
|
||||||
|
note that you may get class/file not found errors if certain proxy
|
||||||
|
classes are not available or failing lazy-loads if new methods were
|
||||||
|
added to the entity class that are not yet in the proxy class. In
|
||||||
|
such a case, simply use the Doctrine Console to (re)generate the
|
||||||
|
proxy classes like so:
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
|
||||||
|
$ ./doctrine orm:generate-proxies
|
||||||
|
|
||||||
|
Autoloading Proxies
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
When you deserialize proxy objects from the session or any other storage
|
||||||
|
it is necessary to have an autoloading mechanism in place for these classes.
|
||||||
|
For implementation reasons Proxy class names are not PSR-0 compliant. This
|
||||||
|
means that you have to register a special autoloader for these classes:
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
|
||||||
|
<?php
|
||||||
|
use Doctrine\ORM\Proxy\Autoloader;
|
||||||
|
|
||||||
|
$proxyDir = "/path/to/proxies";
|
||||||
|
$proxyNamespace = "MyProxies";
|
||||||
|
|
||||||
|
Autoloader::register($proxyDir, $proxyNamespace);
|
||||||
|
|
||||||
|
If you want to execute additional logic to intercept the proxy file not found
|
||||||
|
state you can pass a closure as the third argument. It will be called with
|
||||||
|
the arguments proxydir, namespace and className when the proxy file could not
|
||||||
|
be found.
|
||||||
|
|
||||||
|
Multiple Metadata Sources
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
When using different components using Doctrine 2 you may end up
|
||||||
|
with them using two different metadata drivers, for example XML and
|
||||||
|
YAML. You can use the DriverChain Metadata implementations to
|
||||||
|
aggregate these drivers based on namespaces:
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
|
||||||
|
<?php
|
||||||
|
use Doctrine\ORM\Mapping\Driver\DriverChain;
|
||||||
|
|
||||||
|
$chain = new DriverChain();
|
||||||
|
$chain->addDriver($xmlDriver, 'Doctrine\Tests\Models\Company');
|
||||||
|
$chain->addDriver($yamlDriver, 'Doctrine\Tests\ORM\Mapping');
|
||||||
|
|
||||||
|
Based on the namespace of the entity the loading of entities is
|
||||||
|
delegated to the appropriate driver. The chain semantics come from
|
||||||
|
the fact that the driver loops through all namespaces and matches
|
||||||
|
the entity class name against the namespace using a
|
||||||
|
``strpos() === 0`` call. This means you need to order the drivers
|
||||||
|
correctly if sub-namespaces use different metadata driver
|
||||||
|
implementations.
|
||||||
|
|
||||||
|
|
||||||
|
Default Repository (***OPTIONAL***)
|
||||||
|
-----------------------------------
|
||||||
|
|
||||||
|
Specifies the FQCN of a subclass of the EntityRepository.
|
||||||
|
That will be available for all entities without a custom repository class.
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
|
||||||
|
<?php
|
||||||
|
$config->setDefaultRepositoryClassName($fqcn);
|
||||||
|
$config->getDefaultRepositoryClassName();
|
||||||
|
|
||||||
|
The default value is ``Doctrine\ORM\EntityRepository``.
|
||||||
|
Any repository class must be a subclass of EntityRepository otherwise you got an ORMException
|
||||||
|
|
||||||
|
Setting up the Console
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
Doctrine uses the Symfony Console component for generating the command
|
||||||
|
line interface. You can take a look at the ``vendor/bin/doctrine.php``
|
||||||
|
script and the ``Doctrine\ORM\Tools\Console\ConsoleRunner`` command
|
||||||
|
for inspiration how to setup the cli.
|
||||||
|
|
||||||
|
In general the required code looks like this:
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
|
||||||
|
<?php
|
||||||
|
$cli = new Application('Doctrine Command Line Interface', \Doctrine\ORM\Version::VERSION);
|
||||||
|
$cli->setCatchExceptions(true);
|
||||||
|
$cli->setHelperSet($helperSet);
|
||||||
|
Doctrine\ORM\Tools\Console\ConsoleRunner::addCommands($cli);
|
||||||
|
$cli->run();
|
||||||
|
|
@ -1,77 +1,36 @@
|
|||||||
Configuration
|
Installation and Configuration
|
||||||
=============
|
==============================
|
||||||
|
|
||||||
Bootstrapping Doctrine is a relatively simple procedure that
|
Doctrine can be installed with `Composer <http://www.getcomposer.org>`_. For
|
||||||
roughly exists of four steps:
|
older versions we still have `PEAR packages
|
||||||
|
<http://pear.doctrine-project.org>`_.
|
||||||
|
|
||||||
- `Installation <reference/installation>`
|
Define the following requirement in your ``composer.json`` file:
|
||||||
- Making sure Doctrine class files can be loaded on demand.
|
|
||||||
- Obtaining an EntityManager instance.
|
::
|
||||||
- Optional: Configuration of the Console Tool
|
|
||||||
|
{
|
||||||
|
"require": {
|
||||||
|
"doctrine/orm": "*"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Then call ``composer install`` from your command line. If you don't know
|
||||||
|
how Composer works, check out their `Getting Started
|
||||||
|
<http://getcomposer.org/doc/00-intro.md>`_ to set up.
|
||||||
|
|
||||||
Class loading
|
Class loading
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
Composer
|
|
||||||
^^^^^^^^
|
|
||||||
|
|
||||||
Autoloading is taken care of by Composer. You just have to include the composer autoload file in your project:
|
Autoloading is taken care of by Composer. You just have to include the composer autoload file in your project:
|
||||||
|
|
||||||
.. code-block:: php
|
.. code-block:: php
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
// Include Composer Autoload
|
// bootstrap.php
|
||||||
|
// Include Composer Autoload (relative to project root).
|
||||||
require_once "vendor/autoload.php";
|
require_once "vendor/autoload.php";
|
||||||
|
|
||||||
Skip the rest of this section unless you are using another installation method.
|
|
||||||
|
|
||||||
Lets start with the class loading setup. We need to set up some
|
|
||||||
class loaders (often called "autoloader") so that Doctrine class
|
|
||||||
files are loaded on demand. The Doctrine namespace contains a very
|
|
||||||
fast and minimalistic class loader that can be used for Doctrine
|
|
||||||
and any other libraries where the coding standards ensure that a
|
|
||||||
class's location in the directory tree is reflected by its name and
|
|
||||||
namespace and where there is a common root namespace.
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
You are not forced to use the Doctrine class loader to
|
|
||||||
load Doctrine classes. Doctrine does not care how the classes are
|
|
||||||
loaded, if you want to use a different class loader or your own to
|
|
||||||
load Doctrine classes, just do that. Along the same lines, the
|
|
||||||
class loader in the Doctrine namespace is not meant to be only used
|
|
||||||
for Doctrine classes, too. It is a generic class loader that can be
|
|
||||||
used for any classes that follow some basic naming standards as
|
|
||||||
described above.
|
|
||||||
|
|
||||||
|
|
||||||
The following example shows the setup of a ``ClassLoader`` for the
|
|
||||||
different types of Doctrine Installations:
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
This assumes you've created some kind of script to test
|
|
||||||
the following code in. Something like a ``test.php`` file.
|
|
||||||
|
|
||||||
Tarball Download
|
|
||||||
^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
.. code-block:: php
|
|
||||||
|
|
||||||
<?php
|
|
||||||
// test.php
|
|
||||||
require 'Doctrine/ORM/Tools/Setup.php';
|
|
||||||
|
|
||||||
$lib = "/path/to/doctrine2-orm/lib";
|
|
||||||
Doctrine\ORM\Tools\Setup::registerAutoloadDirectory($lib);
|
|
||||||
|
|
||||||
Additional Symfony Components
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
All three autoloading setups described above also take care of
|
|
||||||
the autoloading of the Symfony Console and YAML component,
|
|
||||||
which are optional dependencies for Doctrine 2.
|
|
||||||
|
|
||||||
Obtaining an EntityManager
|
Obtaining an EntityManager
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
@ -79,16 +38,12 @@ Once you have prepared the class loading, you acquire an
|
|||||||
*EntityManager* instance. The EntityManager class is the primary
|
*EntityManager* instance. The EntityManager class is the primary
|
||||||
access point to ORM functionality provided by Doctrine.
|
access point to ORM functionality provided by Doctrine.
|
||||||
|
|
||||||
Quick Configuration Example
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
The above example is a complete setup of the required options for Doctrine.
|
|
||||||
You can have this step of your code much simpler and use one of the predefined
|
|
||||||
setup methods:
|
|
||||||
|
|
||||||
.. code-block:: php
|
.. code-block:: php
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
|
// bootstrap.php
|
||||||
|
require_once "vendor/autoload.php";
|
||||||
|
|
||||||
use Doctrine\ORM\Tools\Setup;
|
use Doctrine\ORM\Tools\Setup;
|
||||||
use Doctrine\ORM\EntityManager;
|
use Doctrine\ORM\EntityManager;
|
||||||
|
|
||||||
@ -104,456 +59,36 @@ setup methods:
|
|||||||
);
|
);
|
||||||
|
|
||||||
$config = Setup::createAnnotationMetadataConfiguration($paths, $isDevMode);
|
$config = Setup::createAnnotationMetadataConfiguration($paths, $isDevMode);
|
||||||
$em = EntityManager::create($dbParams, $config);
|
$entityManager = EntityManager::create($dbParams, $config);
|
||||||
|
|
||||||
// or if you prefer yaml or xml
|
Or if you prefer XML:
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
|
||||||
|
<?php
|
||||||
$config = Setup::createXMLMetadataConfiguration($paths, $isDevMode);
|
$config = Setup::createXMLMetadataConfiguration($paths, $isDevMode);
|
||||||
$config = Setup::createYAMLMetadataConfiguration($paths, $isDevMode);
|
$entityManager = EntityManager::create($dbParams, $config);
|
||||||
|
|
||||||
These setup commands make several assumptions:
|
Or if you prefer YAML:
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
|
||||||
|
<?php
|
||||||
|
$config = Setup::createYAMLMetadataConfiguration($paths, $isDevMode);
|
||||||
|
$entityManager = EntityManager::create($dbParams, $config);
|
||||||
|
|
||||||
|
Inside the ``Setup`` methods several assumptions are made:
|
||||||
|
|
||||||
- If `$devMode` is true always use an ``ArrayCache`` and set ``setAutoGenerateProxyClasses(true)``.
|
- If `$devMode` is true always use an ``ArrayCache`` and set ``setAutoGenerateProxyClasses(true)``.
|
||||||
- If `$devMode` is false, check for Caches in the order APC, Xcache, Memcache (127.0.0.1:11211), Redis (127.0.0.1:6379) unless `$cache` is passed as fourth argument.
|
- If `$devMode` is false, check for Caches in the order APC, Xcache, Memcache (127.0.0.1:11211), Redis (127.0.0.1:6379) unless `$cache` is passed as fourth argument.
|
||||||
- If `$devMode` is false, set ``setAutoGenerateProxyClasses(false)``
|
- If `$devMode` is false, set ``setAutoGenerateProxyClasses(false)``
|
||||||
- If third argument `$proxyDir` is not set, use the systems temporary directory.
|
- If third argument `$proxyDir` is not set, use the systems temporary directory.
|
||||||
|
|
||||||
|
If you want to configure Doctrine in more detail, take a look at the `Advanced
|
||||||
|
Configuration <reference/advanced-configuration>` section.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
You can learn more about the connection configuration in the
|
You can learn more about the database connection configuration in the
|
||||||
`Doctrine DBAL connection configuration reference <http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html>`_.
|
`Doctrine DBAL connection configuration reference <http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html>`_.
|
||||||
|
|
||||||
Full Configuration Example
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
The configuration of the EntityManager requires a
|
|
||||||
``Doctrine\ORM\Configuration`` instance as well as some database
|
|
||||||
connection parameters. This example shows all the potential
|
|
||||||
steps of configuration.
|
|
||||||
|
|
||||||
.. code-block:: php
|
|
||||||
|
|
||||||
<?php
|
|
||||||
use Doctrine\ORM\EntityManager,
|
|
||||||
Doctrine\ORM\Configuration;
|
|
||||||
|
|
||||||
// ...
|
|
||||||
|
|
||||||
if ($applicationMode == "development") {
|
|
||||||
$cache = new \Doctrine\Common\Cache\ArrayCache;
|
|
||||||
} else {
|
|
||||||
$cache = new \Doctrine\Common\Cache\ApcCache;
|
|
||||||
}
|
|
||||||
|
|
||||||
$config = new Configuration;
|
|
||||||
$config->setMetadataCacheImpl($cache);
|
|
||||||
$driverImpl = $config->newDefaultAnnotationDriver('/path/to/lib/MyProject/Entities');
|
|
||||||
$config->setMetadataDriverImpl($driverImpl);
|
|
||||||
$config->setQueryCacheImpl($cache);
|
|
||||||
$config->setProxyDir('/path/to/myproject/lib/MyProject/Proxies');
|
|
||||||
$config->setProxyNamespace('MyProject\Proxies');
|
|
||||||
|
|
||||||
if ($applicationMode == "development") {
|
|
||||||
$config->setAutoGenerateProxyClasses(true);
|
|
||||||
} else {
|
|
||||||
$config->setAutoGenerateProxyClasses(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
$connectionOptions = array(
|
|
||||||
'driver' => 'pdo_sqlite',
|
|
||||||
'path' => 'database.sqlite'
|
|
||||||
);
|
|
||||||
|
|
||||||
$em = EntityManager::create($connectionOptions, $config);
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
Do not use Doctrine without a metadata and query cache!
|
|
||||||
Doctrine is optimized for working with caches. The main
|
|
||||||
parts in Doctrine that are optimized for caching are the metadata
|
|
||||||
mapping information with the metadata cache and the DQL to SQL
|
|
||||||
conversions with the query cache. These 2 caches require only an
|
|
||||||
absolute minimum of memory yet they heavily improve the runtime
|
|
||||||
performance of Doctrine. The recommended cache driver to use with
|
|
||||||
Doctrine is `APC <http://www.php.net/apc>`_. APC provides you with
|
|
||||||
an opcode-cache (which is highly recommended anyway) and a very
|
|
||||||
fast in-memory cache storage that you can use for the metadata and
|
|
||||||
query caches as seen in the previous code snippet.
|
|
||||||
|
|
||||||
Configuration Options
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
The following sections describe all the configuration options
|
|
||||||
available on a ``Doctrine\ORM\Configuration`` instance.
|
|
||||||
|
|
||||||
Proxy Directory (***REQUIRED***)
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
.. code-block:: php
|
|
||||||
|
|
||||||
<?php
|
|
||||||
$config->setProxyDir($dir);
|
|
||||||
$config->getProxyDir();
|
|
||||||
|
|
||||||
Gets or sets the directory where Doctrine generates any proxy
|
|
||||||
classes. For a detailed explanation on proxy classes and how they
|
|
||||||
are used in Doctrine, refer to the "Proxy Objects" section further
|
|
||||||
down.
|
|
||||||
|
|
||||||
Proxy Namespace (***REQUIRED***)
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
.. code-block:: php
|
|
||||||
|
|
||||||
<?php
|
|
||||||
$config->setProxyNamespace($namespace);
|
|
||||||
$config->getProxyNamespace();
|
|
||||||
|
|
||||||
Gets or sets the namespace to use for generated proxy classes. For
|
|
||||||
a detailed explanation on proxy classes and how they are used in
|
|
||||||
Doctrine, refer to the "Proxy Objects" section further down.
|
|
||||||
|
|
||||||
Metadata Driver (***REQUIRED***)
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
.. code-block:: php
|
|
||||||
|
|
||||||
<?php
|
|
||||||
$config->setMetadataDriverImpl($driver);
|
|
||||||
$config->getMetadataDriverImpl();
|
|
||||||
|
|
||||||
Gets or sets the metadata driver implementation that is used by
|
|
||||||
Doctrine to acquire the object-relational metadata for your
|
|
||||||
classes.
|
|
||||||
|
|
||||||
There are currently 4 available implementations:
|
|
||||||
|
|
||||||
|
|
||||||
- ``Doctrine\ORM\Mapping\Driver\AnnotationDriver``
|
|
||||||
- ``Doctrine\ORM\Mapping\Driver\XmlDriver``
|
|
||||||
- ``Doctrine\ORM\Mapping\Driver\YamlDriver``
|
|
||||||
- ``Doctrine\ORM\Mapping\Driver\DriverChain``
|
|
||||||
|
|
||||||
Throughout the most part of this manual the AnnotationDriver is
|
|
||||||
used in the examples. For information on the usage of the XmlDriver
|
|
||||||
or YamlDriver please refer to the dedicated chapters
|
|
||||||
``XML Mapping`` and ``YAML Mapping``.
|
|
||||||
|
|
||||||
The annotation driver can be configured with a factory method on
|
|
||||||
the ``Doctrine\ORM\Configuration``:
|
|
||||||
|
|
||||||
.. code-block:: php
|
|
||||||
|
|
||||||
<?php
|
|
||||||
$driverImpl = $config->newDefaultAnnotationDriver('/path/to/lib/MyProject/Entities');
|
|
||||||
$config->setMetadataDriverImpl($driverImpl);
|
|
||||||
|
|
||||||
The path information to the entities is required for the annotation
|
|
||||||
driver, because otherwise mass-operations on all entities through
|
|
||||||
the console could not work correctly. All of metadata drivers
|
|
||||||
accept either a single directory as a string or an array of
|
|
||||||
directories. With this feature a single driver can support multiple
|
|
||||||
directories of Entities.
|
|
||||||
|
|
||||||
Metadata Cache (***RECOMMENDED***)
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
.. code-block:: php
|
|
||||||
|
|
||||||
<?php
|
|
||||||
$config->setMetadataCacheImpl($cache);
|
|
||||||
$config->getMetadataCacheImpl();
|
|
||||||
|
|
||||||
Gets or sets the cache implementation to use for caching metadata
|
|
||||||
information, that is, all the information you supply via
|
|
||||||
annotations, xml or yaml, so that they do not need to be parsed and
|
|
||||||
loaded from scratch on every single request which is a waste of
|
|
||||||
resources. The cache implementation must implement the
|
|
||||||
``Doctrine\Common\Cache\Cache`` interface.
|
|
||||||
|
|
||||||
Usage of a metadata cache is highly recommended.
|
|
||||||
|
|
||||||
The recommended implementations for production are:
|
|
||||||
|
|
||||||
|
|
||||||
- ``Doctrine\Common\Cache\ApcCache``
|
|
||||||
- ``Doctrine\Common\Cache\MemcacheCache``
|
|
||||||
- ``Doctrine\Common\Cache\XcacheCache``
|
|
||||||
- ``Doctrine\Common\Cache\RedisCache``
|
|
||||||
|
|
||||||
For development you should use the
|
|
||||||
``Doctrine\Common\Cache\ArrayCache`` which only caches data on a
|
|
||||||
per-request basis.
|
|
||||||
|
|
||||||
Query Cache (***RECOMMENDED***)
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
.. code-block:: php
|
|
||||||
|
|
||||||
<?php
|
|
||||||
$config->setQueryCacheImpl($cache);
|
|
||||||
$config->getQueryCacheImpl();
|
|
||||||
|
|
||||||
Gets or sets the cache implementation to use for caching DQL
|
|
||||||
queries, that is, the result of a DQL parsing process that includes
|
|
||||||
the final SQL as well as meta information about how to process the
|
|
||||||
SQL result set of a query. Note that the query cache does not
|
|
||||||
affect query results. You do not get stale data. This is a pure
|
|
||||||
optimization cache without any negative side-effects (except some
|
|
||||||
minimal memory usage in your cache).
|
|
||||||
|
|
||||||
Usage of a query cache is highly recommended.
|
|
||||||
|
|
||||||
The recommended implementations for production are:
|
|
||||||
|
|
||||||
|
|
||||||
- ``Doctrine\Common\Cache\ApcCache``
|
|
||||||
- ``Doctrine\Common\Cache\MemcacheCache``
|
|
||||||
- ``Doctrine\Common\Cache\XcacheCache``
|
|
||||||
- ``Doctrine\Common\Cache\RedisCache``
|
|
||||||
|
|
||||||
For development you should use the
|
|
||||||
``Doctrine\Common\Cache\ArrayCache`` which only caches data on a
|
|
||||||
per-request basis.
|
|
||||||
|
|
||||||
SQL Logger (***Optional***)
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
.. code-block:: php
|
|
||||||
|
|
||||||
<?php
|
|
||||||
$config->setSQLLogger($logger);
|
|
||||||
$config->getSQLLogger();
|
|
||||||
|
|
||||||
Gets or sets the logger to use for logging all SQL statements
|
|
||||||
executed by Doctrine. The logger class must implement the
|
|
||||||
``Doctrine\DBAL\Logging\SQLLogger`` interface. A simple default
|
|
||||||
implementation that logs to the standard output using ``echo`` and
|
|
||||||
``var_dump`` can be found at
|
|
||||||
``Doctrine\DBAL\Logging\EchoSQLLogger``.
|
|
||||||
|
|
||||||
Auto-generating Proxy Classes (***OPTIONAL***)
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
.. code-block:: php
|
|
||||||
|
|
||||||
<?php
|
|
||||||
$config->setAutoGenerateProxyClasses($bool);
|
|
||||||
$config->getAutoGenerateProxyClasses();
|
|
||||||
|
|
||||||
Gets or sets whether proxy classes should be generated
|
|
||||||
automatically at runtime by Doctrine. If set to ``FALSE``, proxy
|
|
||||||
classes must be generated manually through the doctrine command
|
|
||||||
line task ``generate-proxies``. The strongly recommended value for
|
|
||||||
a production environment is ``FALSE``.
|
|
||||||
|
|
||||||
Development vs Production Configuration
|
|
||||||
---------------------------------------
|
|
||||||
|
|
||||||
You should code your Doctrine2 bootstrapping with two different
|
|
||||||
runtime models in mind. There are some serious benefits of using
|
|
||||||
APC or Memcache in production. In development however this will
|
|
||||||
frequently give you fatal errors, when you change your entities and
|
|
||||||
the cache still keeps the outdated metadata. That is why we
|
|
||||||
recommend the ``ArrayCache`` for development.
|
|
||||||
|
|
||||||
Furthermore you should have the Auto-generating Proxy Classes
|
|
||||||
option to true in development and to false in production. If this
|
|
||||||
option is set to ``TRUE`` it can seriously hurt your script
|
|
||||||
performance if several proxy classes are re-generated during script
|
|
||||||
execution. Filesystem calls of that magnitude can even slower than
|
|
||||||
all the database queries Doctrine issues. Additionally writing a
|
|
||||||
proxy sets an exclusive file lock which can cause serious
|
|
||||||
performance bottlenecks in systems with regular concurrent
|
|
||||||
requests.
|
|
||||||
|
|
||||||
Connection Options
|
|
||||||
------------------
|
|
||||||
|
|
||||||
The ``$connectionOptions`` passed as the first argument to
|
|
||||||
``EntityManager::create()`` has to be either an array or an
|
|
||||||
instance of ``Doctrine\DBAL\Connection``. If an array is passed it
|
|
||||||
is directly passed along to the DBAL Factory
|
|
||||||
``Doctrine\DBAL\DriverManager::getConnection()``. The DBAL
|
|
||||||
configuration is explained in the
|
|
||||||
`DBAL section <./../../../../../dbal/2.0/docs/reference/configuration/en>`_.
|
|
||||||
|
|
||||||
Proxy Objects
|
|
||||||
-------------
|
|
||||||
|
|
||||||
A proxy object is an object that is put in place or used instead of
|
|
||||||
the "real" object. A proxy object can add behavior to the object
|
|
||||||
being proxied without that object being aware of it. In Doctrine 2,
|
|
||||||
proxy objects are used to realize several features but mainly for
|
|
||||||
transparent lazy-loading.
|
|
||||||
|
|
||||||
Proxy objects with their lazy-loading facilities help to keep the
|
|
||||||
subset of objects that are already in memory connected to the rest
|
|
||||||
of the objects. This is an essential property as without it there
|
|
||||||
would always be fragile partial objects at the outer edges of your
|
|
||||||
object graph.
|
|
||||||
|
|
||||||
Doctrine 2 implements a variant of the proxy pattern where it
|
|
||||||
generates classes that extend your entity classes and adds
|
|
||||||
lazy-loading capabilities to them. Doctrine can then give you an
|
|
||||||
instance of such a proxy class whenever you request an object of
|
|
||||||
the class being proxied. This happens in two situations:
|
|
||||||
|
|
||||||
Reference Proxies
|
|
||||||
~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
The method ``EntityManager#getReference($entityName, $identifier)``
|
|
||||||
lets you obtain a reference to an entity for which the identifier
|
|
||||||
is known, without loading that entity from the database. This is
|
|
||||||
useful, for example, as a performance enhancement, when you want to
|
|
||||||
establish an association to an entity for which you have the
|
|
||||||
identifier. You could simply do this:
|
|
||||||
|
|
||||||
.. code-block:: php
|
|
||||||
|
|
||||||
<?php
|
|
||||||
// $em instanceof EntityManager, $cart instanceof MyProject\Model\Cart
|
|
||||||
// $itemId comes from somewhere, probably a request parameter
|
|
||||||
$item = $em->getReference('MyProject\Model\Item', $itemId);
|
|
||||||
$cart->addItem($item);
|
|
||||||
|
|
||||||
Here, we added an Item to a Cart without loading the Item from the
|
|
||||||
database. If you invoke any method on the Item instance, it would
|
|
||||||
fully initialize its state transparently from the database. Here
|
|
||||||
$item is actually an instance of the proxy class that was generated
|
|
||||||
for the Item class but your code does not need to care. In fact it
|
|
||||||
**should not care**. Proxy objects should be transparent to your
|
|
||||||
code.
|
|
||||||
|
|
||||||
Association proxies
|
|
||||||
~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
The second most important situation where Doctrine uses proxy
|
|
||||||
objects is when querying for objects. Whenever you query for an
|
|
||||||
object that has a single-valued association to another object that
|
|
||||||
is configured LAZY, without joining that association in the same
|
|
||||||
query, Doctrine puts proxy objects in place where normally the
|
|
||||||
associated object would be. Just like other proxies it will
|
|
||||||
transparently initialize itself on first access.
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
Joining an association in a DQL or native query
|
|
||||||
essentially means eager loading of that association in that query.
|
|
||||||
This will override the 'fetch' option specified in the mapping for
|
|
||||||
that association, but only for that query.
|
|
||||||
|
|
||||||
|
|
||||||
Generating Proxy classes
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Proxy classes can either be generated manually through the Doctrine
|
|
||||||
Console or automatically by Doctrine. The configuration option that
|
|
||||||
controls this behavior is:
|
|
||||||
|
|
||||||
.. code-block:: php
|
|
||||||
|
|
||||||
<?php
|
|
||||||
$config->setAutoGenerateProxyClasses($bool);
|
|
||||||
$config->getAutoGenerateProxyClasses();
|
|
||||||
|
|
||||||
The default value is ``TRUE`` for convenient development. However,
|
|
||||||
this setting is not optimal for performance and therefore not
|
|
||||||
recommended for a production environment. To eliminate the overhead
|
|
||||||
of proxy class generation during runtime, set this configuration
|
|
||||||
option to ``FALSE``. When you do this in a development environment,
|
|
||||||
note that you may get class/file not found errors if certain proxy
|
|
||||||
classes are not available or failing lazy-loads if new methods were
|
|
||||||
added to the entity class that are not yet in the proxy class. In
|
|
||||||
such a case, simply use the Doctrine Console to (re)generate the
|
|
||||||
proxy classes like so:
|
|
||||||
|
|
||||||
.. code-block:: php
|
|
||||||
|
|
||||||
$ ./doctrine orm:generate-proxies
|
|
||||||
|
|
||||||
Autoloading Proxies
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
When you deserialize proxy objects from the session or any other storage
|
|
||||||
it is necessary to have an autoloading mechanism in place for these classes.
|
|
||||||
For implementation reasons Proxy class names are not PSR-0 compliant. This
|
|
||||||
means that you have to register a special autoloader for these classes:
|
|
||||||
|
|
||||||
.. code-block:: php
|
|
||||||
|
|
||||||
<?php
|
|
||||||
use Doctrine\ORM\Proxy\Autoloader;
|
|
||||||
|
|
||||||
$proxyDir = "/path/to/proxies";
|
|
||||||
$proxyNamespace = "MyProxies";
|
|
||||||
|
|
||||||
Autoloader::register($proxyDir, $proxyNamespace);
|
|
||||||
|
|
||||||
If you want to execute additional logic to intercept the proxy file not found
|
|
||||||
state you can pass a closure as the third argument. It will be called with
|
|
||||||
the arguments proxydir, namespace and className when the proxy file could not
|
|
||||||
be found.
|
|
||||||
|
|
||||||
Multiple Metadata Sources
|
|
||||||
-------------------------
|
|
||||||
|
|
||||||
When using different components using Doctrine 2 you may end up
|
|
||||||
with them using two different metadata drivers, for example XML and
|
|
||||||
YAML. You can use the DriverChain Metadata implementations to
|
|
||||||
aggregate these drivers based on namespaces:
|
|
||||||
|
|
||||||
.. code-block:: php
|
|
||||||
|
|
||||||
<?php
|
|
||||||
use Doctrine\ORM\Mapping\Driver\DriverChain;
|
|
||||||
|
|
||||||
$chain = new DriverChain();
|
|
||||||
$chain->addDriver($xmlDriver, 'Doctrine\Tests\Models\Company');
|
|
||||||
$chain->addDriver($yamlDriver, 'Doctrine\Tests\ORM\Mapping');
|
|
||||||
|
|
||||||
Based on the namespace of the entity the loading of entities is
|
|
||||||
delegated to the appropriate driver. The chain semantics come from
|
|
||||||
the fact that the driver loops through all namespaces and matches
|
|
||||||
the entity class name against the namespace using a
|
|
||||||
``strpos() === 0`` call. This means you need to order the drivers
|
|
||||||
correctly if sub-namespaces use different metadata driver
|
|
||||||
implementations.
|
|
||||||
|
|
||||||
|
|
||||||
Default Repository (***OPTIONAL***)
|
|
||||||
-----------------------------------
|
|
||||||
|
|
||||||
Specifies the FQCN of a subclass of the EntityRepository.
|
|
||||||
That will be available for all entities without a custom repository class.
|
|
||||||
|
|
||||||
.. code-block:: php
|
|
||||||
|
|
||||||
<?php
|
|
||||||
$config->setDefaultRepositoryClassName($fqcn);
|
|
||||||
$config->getDefaultRepositoryClassName();
|
|
||||||
|
|
||||||
The default value is ``Doctrine\ORM\EntityRepository``.
|
|
||||||
Any repository class must be a subclass of EntityRepository otherwise you got an ORMException
|
|
||||||
|
|
||||||
Setting up the Console
|
|
||||||
----------------------
|
|
||||||
|
|
||||||
Doctrine uses the Symfony Console component for generating the command
|
|
||||||
line interface. You can take a look at the ``bin/doctrine.php``
|
|
||||||
script and the ``Doctrine\ORM\Tools\Console\ConsoleRunner`` command
|
|
||||||
for inspiration how to setup the cli.
|
|
||||||
|
|
||||||
If you installed Doctrine 2 through Composer, then the Doctrine command is
|
|
||||||
available to you in the bin-dir, by default at ``vendor/bin/doctrine-orm``.
|
|
||||||
|
|
||||||
In general the required code looks like this:
|
|
||||||
|
|
||||||
.. code-block:: php
|
|
||||||
|
|
||||||
<?php
|
|
||||||
$cli = new Application('Doctrine Command Line Interface', \Doctrine\ORM\Version::VERSION);
|
|
||||||
$cli->setCatchExceptions(true);
|
|
||||||
$cli->setHelperSet($helperSet);
|
|
||||||
Doctrine\ORM\Tools\Console\ConsoleRunner::addCommands($cli);
|
|
||||||
$cli->run();
|
|
||||||
|
|
||||||
|
@ -1,18 +1,5 @@
|
|||||||
Installation
|
Installation
|
||||||
============
|
============
|
||||||
|
|
||||||
Doctrine was installable in many different ways, however `Composer <http://www.getcomposer.org>`_ turned out to be one of the best things for PHP in a long time.
|
The installation chapter has moved to `Installation and Configuration
|
||||||
This is why we moved all installation to use Composer only.
|
<reference/configuration>`_.
|
||||||
|
|
||||||
Define the following requirement in your ``composer.json`` file:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
{
|
|
||||||
"require": {
|
|
||||||
"doctrine/orm": "*"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Then run the composer command and you are done. Continue with the
|
|
||||||
:doc:`Configuration <configuration>`.
|
|
||||||
|
@ -1,296 +0,0 @@
|
|||||||
Doctrine explained in 10 quick steps
|
|
||||||
====================================
|
|
||||||
|
|
||||||
You can follow this tutorial step by step yourself and end up with a simple
|
|
||||||
Doctrine application. It assumed that you installed Doctrine via Composer.
|
|
||||||
For more information take a look at the :doc:`Installation help
|
|
||||||
<../reference/introduction>`.
|
|
||||||
|
|
||||||
1. Allows you to map PHP Objects to database tables
|
|
||||||
---------------------------------------------------
|
|
||||||
|
|
||||||
.. code-block:: php
|
|
||||||
|
|
||||||
<?php
|
|
||||||
class Post
|
|
||||||
{
|
|
||||||
protected $id;
|
|
||||||
protected $title;
|
|
||||||
protected $body;
|
|
||||||
}
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
mysql> CREATE TABLE Post (id INT AUTO_INCREMENT PRIMARY KEY, title
|
|
||||||
VARCHAR(255), body TEXT);
|
|
||||||
|
|
||||||
mysql> DESCRIBE Post;
|
|
||||||
+-------+--------------+------+-----+---------+----------------+
|
|
||||||
| Field | Type | Null | Key | Default | Extra |
|
|
||||||
+-------+--------------+------+-----+---------+----------------+
|
|
||||||
| id | int(11) | NO | PRI | NULL | auto_increment |
|
|
||||||
| title | varchar(255) | YES | | NULL | |
|
|
||||||
| body | text | YES | | NULL | |
|
|
||||||
+-------+--------------+------+-----+---------+----------------+
|
|
||||||
|
|
||||||
.. tip::
|
|
||||||
|
|
||||||
Objects mapped with Doctrine are called Entities. They don't need to extend
|
|
||||||
a base class and even allow constructors with required parameters.
|
|
||||||
|
|
||||||
You are responsible for implementing getters, setters and constructors of
|
|
||||||
your entities yourself. This gives you full freedom to design your business
|
|
||||||
objects as you wish.
|
|
||||||
|
|
||||||
2. Using Annotations, XML or YAML for Metadata Mapping
|
|
||||||
------------------------------------------------------
|
|
||||||
|
|
||||||
.. configuration-block::
|
|
||||||
|
|
||||||
.. code-block:: php
|
|
||||||
|
|
||||||
<?php
|
|
||||||
/** @Entity **/
|
|
||||||
class Post
|
|
||||||
{
|
|
||||||
/** @Id @GeneratedValue @Column(type="integer") **/
|
|
||||||
protected $id;
|
|
||||||
/** @Column(type="string") **/
|
|
||||||
protected $title;
|
|
||||||
/** @Column(type="text") **/
|
|
||||||
protected $body;
|
|
||||||
}
|
|
||||||
|
|
||||||
.. code-block:: yaml
|
|
||||||
|
|
||||||
Post:
|
|
||||||
type: entity
|
|
||||||
id:
|
|
||||||
id:
|
|
||||||
type: integer
|
|
||||||
generator:
|
|
||||||
strategy: AUTO
|
|
||||||
fields:
|
|
||||||
title:
|
|
||||||
type: string
|
|
||||||
body:
|
|
||||||
type: text
|
|
||||||
|
|
||||||
.. code-block:: xml
|
|
||||||
|
|
||||||
<?xml version="1.0" ?>
|
|
||||||
<doctrine-mapping>
|
|
||||||
<entity name="Post">
|
|
||||||
<id name="id type="integer">
|
|
||||||
<generator strategy="AUTO" />
|
|
||||||
</id>
|
|
||||||
<field name="title" type="string" />
|
|
||||||
<field name="body" type="text" />
|
|
||||||
</entity>
|
|
||||||
</doctrine-mapping>
|
|
||||||
|
|
||||||
|
|
||||||
3. Object References map to Foreign keys
|
|
||||||
----------------------------------------
|
|
||||||
|
|
||||||
.. code-block:: php
|
|
||||||
|
|
||||||
<?php
|
|
||||||
/** @Entity **/
|
|
||||||
class Post
|
|
||||||
{
|
|
||||||
// .. previous code
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @ManyToOne(targetEntity="User")
|
|
||||||
**/
|
|
||||||
protected $author;
|
|
||||||
|
|
||||||
public function __construct(User $user)
|
|
||||||
{
|
|
||||||
$this->author = $user;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @Entity **/
|
|
||||||
class User
|
|
||||||
{
|
|
||||||
/** @Id @GeneratedValue @Column(type="integer") **/
|
|
||||||
protected $id;
|
|
||||||
/** @Column(type="string") **/
|
|
||||||
protected $name;
|
|
||||||
}
|
|
||||||
|
|
||||||
$user = new User();
|
|
||||||
$post = new Post($user);
|
|
||||||
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
mysql> CREATE TABLE Post (id INT AUTO_INCREMENT PRIMARY KEY, title
|
|
||||||
VARCHAR(255), body TEXT, author_id INT);
|
|
||||||
|
|
||||||
mysql> CREATE TABLE User (id INT AUTO_INCREMENT PRIMARY KEY, name
|
|
||||||
VARCHAR(255));
|
|
||||||
|
|
||||||
mysql> ALTER TABLE Post ADD FOREIGN KEY (author_id) REFERENCES User (id);
|
|
||||||
|
|
||||||
mysql> DESCRIBE Post;
|
|
||||||
+-----------+--------------+------+-----+---------+----------------+
|
|
||||||
| Field | Type | Null | Key | Default | Extra |
|
|
||||||
+-----------+--------------+------+-----+---------+----------------+
|
|
||||||
| id | int(11) | NO | PRI | NULL | auto_increment |
|
|
||||||
| title | varchar(255) | YES | | NULL | |
|
|
||||||
| body | text | YES | | NULL | |
|
|
||||||
| author_id | int(11) | YES | MUL | NULL | |
|
|
||||||
+-----------+--------------+------+-----+---------+----------------+
|
|
||||||
|
|
||||||
.. tip::
|
|
||||||
|
|
||||||
This means you don't have to mess with foreign keys yourself, just use
|
|
||||||
references to connect objects with each other and let Doctrine handle the
|
|
||||||
rest.
|
|
||||||
|
|
||||||
4. Collections handle sets of objects references
|
|
||||||
------------------------------------------------
|
|
||||||
|
|
||||||
.. code-block:: php
|
|
||||||
|
|
||||||
<?php
|
|
||||||
use Doctrine\Common\Collections\ArrayCollection;
|
|
||||||
|
|
||||||
class Post
|
|
||||||
{
|
|
||||||
// .. previous code
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @OneToMany(targetEntity="Comment", mappedBy="post",
|
|
||||||
* cascade={"persist"})
|
|
||||||
**/
|
|
||||||
protected $comments;
|
|
||||||
|
|
||||||
public function __construct(User $author)
|
|
||||||
{
|
|
||||||
$this->author = $author;
|
|
||||||
$this->comments = new ArrayCollection();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function addComment($text)
|
|
||||||
{
|
|
||||||
$this->comments[] = new Comment($this, $text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @Entity **/
|
|
||||||
class Comment
|
|
||||||
{
|
|
||||||
/** @Id @GeneratedValue @Column(type="integer") **/
|
|
||||||
protected $id;
|
|
||||||
/** @Column(type="text") **/
|
|
||||||
protected $comment;
|
|
||||||
/**
|
|
||||||
* @ManyToOne(targetEntity="Post", inversedBy="comments")
|
|
||||||
**/
|
|
||||||
protected $post;
|
|
||||||
|
|
||||||
public function __construct(Post $post, $text)
|
|
||||||
{
|
|
||||||
$this->post = $post;
|
|
||||||
$this->comment = $text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$post->addComment("First..");
|
|
||||||
$post->addComment("Second!");
|
|
||||||
|
|
||||||
5. Easy to setup for the default configuration case
|
|
||||||
---------------------------------------------------
|
|
||||||
|
|
||||||
.. code-block:: php
|
|
||||||
|
|
||||||
<?php
|
|
||||||
use Doctrine\ORM\Tools\Setup;
|
|
||||||
use Doctrine\ORM\EntityManager;
|
|
||||||
|
|
||||||
require_once "vendor/autoload.php";
|
|
||||||
|
|
||||||
$dbParams = array(
|
|
||||||
'driver' => 'pdo_mysql',
|
|
||||||
'user' => 'root',
|
|
||||||
'password' => '',
|
|
||||||
'dbname' => 'tests'
|
|
||||||
);
|
|
||||||
$path = 'path/to/entities';
|
|
||||||
$config = Setup::createAnnotationMetadataConfiguration($path, true);
|
|
||||||
$entityManager = EntityManager::create($dbParams, $config);
|
|
||||||
|
|
||||||
|
|
||||||
6. The EntityManager needs to know about your new objects
|
|
||||||
---------------------------------------------------------
|
|
||||||
|
|
||||||
.. code-block:: php
|
|
||||||
|
|
||||||
<?php
|
|
||||||
|
|
||||||
$entityManager->persist($user);
|
|
||||||
$entityManager->persist($post);
|
|
||||||
|
|
||||||
.. warning::
|
|
||||||
|
|
||||||
This does not lead to INSERT/UPDATE statements yet. You need to call
|
|
||||||
EntityManager#flush()
|
|
||||||
|
|
||||||
|
|
||||||
7. EntityManager#flush() batches SQL INSERT/UPDATE/DELETE statements
|
|
||||||
--------------------------------------------------------------------
|
|
||||||
|
|
||||||
.. code-block:: php
|
|
||||||
|
|
||||||
<?php
|
|
||||||
|
|
||||||
$entityManager->flush();
|
|
||||||
|
|
||||||
.. tip::
|
|
||||||
|
|
||||||
Batching all write-operations against the database allows Doctrine to wrap all
|
|
||||||
statements into a single transaction and benefit from other performance
|
|
||||||
optimizations such as prepared statement re-use.
|
|
||||||
|
|
||||||
8. You can fetch objects from the database through the EntityManager
|
|
||||||
--------------------------------------------------------------------
|
|
||||||
|
|
||||||
.. code-block:: php
|
|
||||||
|
|
||||||
<?php
|
|
||||||
|
|
||||||
$post = $entityManager->find("Post", $id);
|
|
||||||
|
|
||||||
9. ..or through a Repository
|
|
||||||
----------------------------
|
|
||||||
|
|
||||||
.. code-block:: php
|
|
||||||
|
|
||||||
<?php
|
|
||||||
|
|
||||||
$authorRepository = $entityManager->getRepository("Author");
|
|
||||||
$author = $authorRepository->find($authorId);
|
|
||||||
|
|
||||||
$postRepository = $entityManager->getRepository("Post");
|
|
||||||
$post = $postRepository->findOneBy(array("title" => "Hello World!"));
|
|
||||||
|
|
||||||
$posts = $repository->findBy(
|
|
||||||
array("author" => $author),
|
|
||||||
array("title" => "ASC")
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
10. Or complex finder scenarios with the Doctrine Query Language
|
|
||||||
----------------------------------------------------------------
|
|
||||||
|
|
||||||
.. code-block:: php
|
|
||||||
|
|
||||||
<?php
|
|
||||||
// all posts and their comment count
|
|
||||||
$dql = "SELECT p, count(c.id) AS comments " .
|
|
||||||
"FROM Post p JOIN p.comments GROUP BY p";
|
|
||||||
$results = $entityManager->createQuery($dql)->getResult();
|
|
Loading…
x
Reference in New Issue
Block a user