Doctrine Cookbook

download Doctrine Cookbook

of 40

  • date post

    28-Oct-2014
  • Category

    Documents

  • view

    142
  • download

    2

Embed Size (px)

Transcript of Doctrine Cookbook

Doctrine Cookbook

Everyday recipes for everyday Doctrine users

Doctrine 2.0License: Creative Commons Attribution-Share Alike 3.0 Unported License Version: cookbook-2.0-en-2010-05-12

Table of Contents

ii

Table of ContentsGetting Started XML-Edition ............................................................................ 3 Implementing ArrayAccess for domain objects .............................................. 18 Option 1 ................................................................................................................... 18 Option 2 ................................................................................................................... 19 Read-only ................................................................................................................. 19 Implementing the NOTIFY changetracking policy ......................................... 21 Implementing NotifyPropertyChanged.................................................................... 21 Validation of Entities ...................................................................................... 23 Implementing wakeup or clone ...................................................................... 26 Safely implementing __wakeup................................................................................ 26 Safely implementing __clone ................................................................................... 26 Summary.................................................................................................................. 27 Integrating with CodeIgniter.......................................................................... 28 Setting up the file structure .................................................................................... 28 Creating your Doctrine CodeIgniter library ............................................................ 28 Now to use it............................................................................................................ 30 DQL Custom Walkers ...................................................................................... 31 DQL User Defined Functions .......................................................................... 36

-----------------

Brought to you by

Chapter 1: Getting Started XML-Edition

3

Chapter 1

Getting Started XML-EditionDoctrine 2 is a project that aims to handle the persistence of the domain model in a noninterfering way. The Data Mapper pattern is at the heart of this project, aiming for a complete separation of the domain/business logic from the persistence in a relational database management system. The benefit of Doctrine for the programmer is the possibility can focus soley on the business and worry about persistence only as a secondary task. This doesn't mean persistence is not important to Doctrine 2, however it is our belief that there are considerable benefits for object-oriented programming, if persistence and entities are kept perfectly seperated.

What are Entities?Entities are leightweight PHP Objects that don't need to extend any abstract base class or interface. An entity class must not be final or contain final methods. Additionally it must not implement __clone nor __wakeup or do so safely1. An entity contains persistable properties. A persistable property is an instance variable of the entity that contains the data which is persisted and retrieved by Doctrine's data mapping capabilities.

An Example Model: Bug TrackerFor this Getting Started Guide for Doctrine we will implement the Bug Tracker domain model from the Zend_Db_Table2 documentation. Reading that documentat we can extract the requirements to be: A Bugs has a description, creation date, status, reporter and engineer A bug can occour on different products (platforms) Products have a name. Bug Reporter and Engineers are both Users of the System. A user can create new bugs. The assigned engineer can close a bug. A user can see all his reported or assigned bugs. Bugs can be paginated through a list-view.

http://www.doctrine-project.org/documentation/cookbook/2_0/en/ implementing-wakeup-or-clone 2. http://framework.zend.com/manual/en/zend.db.table.html1.

-----------------

Brought to you by

Chapter 1: Getting Started XML-Edition

4

WARNING This tutorial is incrementally building up your Doctrine 2 knowledge and even lets you make some mistakes, to show some common pitfalls in mapping Entities to a database. Don't blindly copy-paste the examples here, it is not production ready without the additional comments and knowledge this tutorial teaches.

A first prototypeA first simplified design for this domain model might look like the following set of classes:setProxyDir(__DIR__.'/lib/MyProject/Proxies'); $config->setProxyNamespace('MyProject\Proxies'); $config->setAutoGenerateProxyClasses((APPLICATION_ENV == "development")); // Mapping Configuration (4) $driverImpl = new Doctrine\ORM\Mapping\Driver\XmlDriver(__DIR__."/config/ mappings"); $config->setMetadataDriverImpl($driverImpl); // Caching Configuration (5) if (APPLICATION_ENV == "develoment") { $cache = new \Doctrine\Common\Cache\ArayCache(); } else { $cache = new \Doctrine\Common\Cache\ApcCache(); } $config->setMetadataCacheImpl($cache); $config->setQueryCacheImpl($cache); // database configuration parameters (6) $conn = array( 'driver' => 'pdo_sqlite', 'path' => __DIR__ . '/db.sqlite', ); // obtaining the entity manager (7) $evm = new Doctrine\Common\EventManager() $entityManager = \Doctrine\ORM\EntityManager::create($conn, $config, $evm);

The first block sets up the autoloading capabilities of Doctrine. I am registering the Doctrine namespace to the given path. To add your own namespace you can instantiate another CloassLoader with different namespace and path arguments. There is no requirement to use the Doctrine ClassLoader for your autoloading needs, you can use whatever suits you best. The second block contains of the instantiation of the ORM Configuration object. Besides the configuration shown in the next blocks there are several others with are all explained in the Configuration section of the manual3. The Proxy Configuration is a required block for your application, you have to specifiy where Doctrine writes the PHP code for Proxy Generation. Proxies are children of your entities generated by Doctrine to allow for type-safe lazy loading. We will see in a later chapter how exactly this works. Besides the path to the proxies we also specifiy which namespace they will reside under aswell as a flag autoGenerateProxyClasses indicating that proxies should be re-generated on each request, which is recommended for development. In production this should be prevented at all costs, the proxy class generation can be quite costly. The fourth block contains the mapping driver details. We will use XML Mapping in this example, so we configure the XmlDriver instance with a path to mappings configuration folder where we put the Bug.dcm.xml, Product.dcm.xml and User.dcm.xml.

http://www.doctrine-project.org/documentation/manual/2_0/en/ configuration#configuration-options3.

-----------------

Brought to you by

Chapter 1: Getting Started XML-Edition

12

In the 5th block the caching configuration is set. In production we use caching only on a per request-basis using the ArrayCache. In production it is literally required to use Apc, Memcache or XCache to get the full speed out of Doctrine. Internally Doctrine uses caching heavily for the Metadata and DQL Query Language so make sure you use a caching mechanism. The 6th block shows the configuration options required to connect to a database, in my case a file-based sqlite database. All the configuration options for all the shipped drivers are given in the DBAL Configuration section of the manual. The last block shows how the EntityManager is obtained from a factory method, Here we also pass in an EventManager instance which is optional. However using the EventManager you can hook in to the lifecycle of entities, which is a common use-case, so you know how to configure it already.

Generating the Database SchemaNow that we have defined the Metadata Mappings and bootstrapped the EntityManager we want to generate the relational database schema from it. Doctrine has a Command-LineInterface that allows you to access the SchemaTool, a component that generates the required tables to work with the metadata. For the commandline tool to work a cli-config.php file has to be present in the project root directry, where you will execute the doctrine command. Its a fairly simple file:createQueryBuilder() which is a Query Object around the DQL language. As a last resort you can however also use Native SQL and a description of the result set to retrieve entities from the database. DQL boils down to a Native SQL statement and a ResultSetMapping instance itself. Using Native SQL you could even use stored procedures for data retrieval, or make use of advanced non-portable database queries like PostgreSql's recursive queries.

The next Use-Case is displaying a Bug by primary key. This could be done using DQL as in the previous example with a where clause, however there is a convenience method on the Entity Manager that handles loading by primary key, which we have already seen in the write scenarios:_load(); return parent::addReportedBug($bug); } public function assignedToBug($bug) { $this->_load(); return parent::assignedToBug($bug); } }

See how upon each method call the proxy is lazily loaded from the database? Using public properties however we never call a method and Doctrine has no way to hook into the PHP Engine to detect this access and trigger the lazy load. We need to revise our entities, make all the propertie