Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                                                  Doctrine 2
                              Enterprise Persistence Layer for PHP 5.3




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                                   Jonathan H. Wage
  •    Web developer for a decade
  •    Open Source Evangelist
  •    Published Author
  •    Contributes to...
  •    ...Doctrine
  •    ...Symfony
  •    ...and more
  •    Employee of Sensio Labs, the creators of
       Symfony
Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                                   Jonathan H. Wage
  • http://www.twitter.com/jwage

  • http://www.jwage.com

  • http://www.facebook.com/jwage

       You can contact Jonathan about Doctrine and Open-Source or for
       training, consulting, application development, or business related
                    questions at jonathan.wage@sensio.com


Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




      How many have used Doctrine?
  •    Before 1.0?
  •    1.0?
  •    1.1?
  •    1.2?
  •    2.0?




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                                              Doctrine 1.0
  • First commit April 13th 2006

  • Finished and Released September 1st 2008

  • One of the first true ORM implementation for PHP

  • First LTS(long term support) release. Maintained
    until March 1st 2010

  • Integrated with many popular frameworks:
    Symfony, Zend Framework, Code Igniter, etc.
Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                                              Doctrine 1.1
  • Continued evolution of 1.0

  • Dozens of small improvements

  • Several significant new features

  • Too many bug fixes to count



Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                                              Doctrine 1.2
  • Last LTS release of the Doctrine 1.x series

  • More bug fixes

  • More improvements

  • Even more new features

  • Scheduled to release this month

Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                   Doctrine 2.0

Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                                    Requires PHP 5.3




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




            Three Main Packages



Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                                               Common



Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3    www.doctrine-project.org   www.sensiolabs.com




                                                        DBAL



Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                                                        ORM



Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




       Fully implements namespaces




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                                 Namespaced Code
       namespace DoctrineORM;

       use DoctrineORMQueryExpr,
           DoctrineCommonDoctrineException;

       /**
         * This class is responsible for building DQL query strings via an object oriented
         * PHP interface.
         *
         * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
         * @link    www.doctrine-project.org
         * @since   2.0
         * @version $Revision$
         * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
         * @author Jonathan Wage <jonwage@gmail.com>
         * @author Roman Borschel <roman@code-factory.org>
         */
       class QueryBuilder
       {




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                                Using Namespaces

                           use DoctrineORMQueryBuilder;

                           $qb = new QueryBuilder($em);
                           $qb->select('u')
                              ->from('ModelsUser', 'u')
                              ->orderBy('u.username', 'ASC');

                           $q = $qb->getQuery();
                           $users = $q->execute();




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                 Follows PHP 5.3 technical
                 interoperability standards

    http://groups.google.com/group/php-standards/web/php-coding-standard-version-2




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                          What does this mean?
  • PHP libraries will finally be 100% technically interoperable
    and have optimum autoloading performance

  • Symfony 2.0 + Doctrine 2.0 + Zend Framework 2.0

  • Load classes from 3 different libraries with one
    autoloader and one include path

  • Share SplClassLoader implementation: http://
    gist.github.com/221634

  • Implement SplClassLoader in C/PHP :)

Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                     Performance of PHP 5.3




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




    Doctrine 1 and 2 get significant
    performance increase from 5.3




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                      30% Less Memory Used




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                                                  20% Faster




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                                    What’s my point?

                                USE PHP 5.3!


Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                            Let the numbers talk

                                           Doctrine 1.1
                                           4.3 seconds for 5000 records

                                           Doctrine 2.0
                                           1.4 seconds for 5000 records

                                           Doctrine 2.0
                                           3.5 seconds for 10000 records




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                                Doctrine 2 is FAST!




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




       The code isn’t that bad on the
                eyes either




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




            Quit imposing on my
              domain model!!


Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                                The Doctrine 1 Way

                    class User extends Doctrine_Record
                    {
                        public function setTableDefinition()
                        {
                            $this->hasColumn('id', 'integer', null, array(
                              'primary' => true,
                              'auto_increment' => true
                            ));

                                    $this->hasColumn('username', 'string', 255);
                            }
                    }




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                           What is the problem?
  • We have to extend Doctrine_Record

  • It imposes methods, properties, and other
    junk on our domain model objects

  • We have to instantiate a dummy User in
    order to instantiate the metadata for the
    model

  • Slow, ugly and just not pretty :)
Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                    The new Doctrine 2 Way
             Specify mapping information with doc block
              annotations, yaml, xml, or raw PHP code.




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                                    With Annotations
                            /**
                              * @Entity
                              * @Table(name="user")
                              */
                            class User
                            {
                                 /**
                                  * @Id
                                  * @Column(type="integer")
                                  * @GeneratedValue(strategy="auto")
                                  */
                                 public $id;

                                   /**
                                    * @Column(type="string", length=255)
                                    */
                                   public $username;
                            }




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3      www.doctrine-project.org   www.sensiolabs.com




                                                  With YAML

                                                   EntitiesUser:
                                                     type: entity
                                                     table: users
                                                     fields:
                                                       id:
                                                         type: integer
                                                         id: true
                                                         generator:
                                                           strategy: AUTO
                                                       name:
                                                         type: string(50)




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3     www.doctrine-project.org   www.sensiolabs.com




                                                        With XML

              <?xml version="1.0" encoding="utf-8"?>
              <doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xsi="http://
              www.w3.org/2001/XMLSchema-instance" schemaLocation="http://doctrine-project.org/schemas/orm/
              doctrine-mapping.xsd">
                  <entity name="EntitiesUser" table="users">
                      <field name="name" type="string" column="name" length="50" precision="0" scale="0">
                          <options/>
                      </field>
                      <id name="id" type="integer" column="id">
                          <generator strategy="AUTO"/>
                      </id>
                  </entity>
              </doctrine-mapping>




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3     www.doctrine-project.org   www.sensiolabs.com




                                                        With PHP
                 use DoctrineORMMappingClassMetadataInfo;

                 $metadata->setInheritanceType(ClassMetadataInfo::INHERITANCE_TYPE_NONE);
                 $metadata->setPrimaryTable(array(
                     'name' => 'users',
                 ));
                 $metadata->mapField(array(
                     'fieldName' => 'id',
                     'type' => 'integer',
                     'id' => true,
                     'columnName' => 'id',
                 ));
                 $metadata->mapField(array(
                     'fieldName' => 'name',
                     'type' => 'string',
                     'length' => '50',
                     'columnName' => 'name',
                 ));
                 $metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_AUTO);




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3     www.doctrine-project.org   www.sensiolabs.com




                          No more base class...
                                    $user = new EntitiesUser();
                                    $user->setUsername('jwage');
                                    print_r($user);


                                                    User Object
                                                    (
                                                      [id] =>
                                                      [username] => jwage
                                                    )



     ...means a clean domain model
Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




 Doctrine 2 is heavily decoupled
so you can use things standalone




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




    Use the DBAL without the ORM!




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




             Database Abstraction Layer
  • The Doctrine DBAL is a very powerful
    project in itself

  • Based off of code borrowed from other
    projects

  • PEAR MDB2

  • Zend_Db

Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




             Database Abstraction Layer
  • Using the Doctrine DBAL standalone is a
    good option for your PHP projects if a fully
    featured ORM is not needed

  • API for performing DDL statements,
    executing queries, etc.

  • Connect to different types of databases:
    mysql, sqlite, pgsql, oracle, etc.


Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                            DBAL Examples



Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




       Create a Connection to MySQL

          $params = array(
              'driver' => 'pdo_mysql',
              'host' => 'localhost',
              'user' => 'root',
              'password' => '',
              'dbname' => 'doctrine2dbal'
          );
          $conn = DoctrineDBALDriverManager::getConnection($params);




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                   Get the Schema Manager



                              $sm = $conn->getSchemaManager();




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                                    Schema Manager

  • Issue DDL statements through intuitive API:
    createTable(), dropTable(),
    createForeignKey(), etc.



  • Introspect your database schema as well:
    listTables(), listTableColumns(), listUsers(),
    etc.


Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                    Drop and Create a Table
                             $columns = array(
                                 'id' => array(
                                     'type' => Type::getType('integer'),
                                     'autoincrement' => true,
                                     'primary' => true,
                                     'notnull' => true
                                 ),
                                 'name' => array(
                                     'type' => Type::getType('string'),
                                     'length' => 255
                                 ),
                             );

                             $sm->dropAndCreateTable('user', $columns);



Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                            Create a Foreign Key


                          $definition = array(
                              'name' => 'user_id_fk',
                              'local' => 'user_id',
                              'foreign' => 'id',
                              'foreignTable' => 'user'
                          );
                          $sm->createForeignKey('profile', $definition);




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                                     So much more...
  • Fully featured DBAL for manipulating your
    database with DDL statements

  • Introspect your database and learn about it

  • Execute queries and retrieve data

  • Support for transactions


Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




           The ORM Key Feature



Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                        Doctrine Query
                          Language


Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




       DQL stands for Doctrine Query
           Language and is heavily
     influenced by HQL from Hibernate



Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                      Proprietary OQL(object
                      query language) dialect




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                     The DQL is parsed by a
                      hand written recursive
                         descent parser



Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                                       Constructs AST




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




             AST = Abstract Syntax Tree




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




         Tree representation of the
       syntactic structure of a source
                  language



Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




            PHP class names of DQL parser directly
                 represent the language itself

                                              OrderByClause.php
                                              SelectClause.php
                                              SelectExpression.php
                                              Subselect.php
                                              DeleteClause.php
                                              etc. etc.




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




       Every DQL feature has a
      class to handle the parsing



Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




  • Easy to use

  • Easy to expand and add new features

  • Easy to use and understand the parsing of a
    DQL string

  • Expand the DQL parser with your own
    functionality and add to the DQL language

Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




      DQL parser is very fast as it is.
        With final SQL caching it
           becomes invisible.



Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                                Sample DQL Query

                      $query = $em->createQuery(
                          'SELECT u, g, FROM User u ' .
                          'LEFT JOIN u.Groups g ' .
                          'ORDER BY u.name ASC, g.name ASC'
                      );
                      $users = $query->execute();




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                       Using the QueryBuilder

                           $qb = $em->createQueryBuilder()
                               ->select('u, g')
                               ->from('User', 'u')
                               ->leftJoin('u.Groups', 'g')
                               ->orderBy('u.name', 'ASC')
                               ->addOrderBy('g.name', 'ASC');

                           $query = $qb->getQuery();




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                                  Executing Queries

             $users = $query->execute();

             foreach ($users as $user) {
                 // ...
                 foreach ($user->getGroups() as $group) {
                     // ...
                 }
             }




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                           Working with Entities




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                                The EntityManager




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                  The EntityManager is
                responsible for managing
                the persistence of entities



Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




             Creating the EntityManager

         $config = new DoctrineORMConfiguration();
         $config->setMetadataCacheImpl(new DoctrineCommonCacheArrayCache);
         $config->setProxyDir(__DIR__ . '/Proxies');
         $config->setProxyNamespace('Proxies');

         $connectionOptions = array(
             'driver' => 'pdo_sqlite',
             'path' => 'database.sqlite'
         );

         $em = DoctrineORMEntityManager::create($connectionOptions, $config);




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                                  Persisting Entities
                                   $user = new User;
                                   $user->setUsername('jwage');
                                   $user->setPassword('changeme');

                                   $profile = new Profile;
                                   $profile->setName('Jonathan H. Wage');

                                   $user->setProfile($user);

                                   $em->persist($user);
                                   $em->persist($profile);

                                   $em->flush();




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                                     Deleting Entities

                                $user1 = $em->find('User', 1);
                                $user2 = $em->find('User', 2);

                                $em->remove($user1);
                                $em->remove($user2);
                                $em->flush();




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                         EntityManager::flush()
  • Commits any changes to the managed
    entities

  • Efficiently executes insert, update and
    delete statements

  • Keep number of flush() operations down to
    about 1-2 times per request



Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                        The EntityManager::flush()
                        operation is able to insert,
                      update and delete entities very
                       efficiently. It is ideal to keep
                      your flush operations to about
                           1-2 times per request



Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                                       Metadata Cache



   $config = new DoctrineORMConfiguration();
   $config->setMetadataCacheImpl(new DoctrineCommonCacheApcCache);




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




              In production cache the
             ClassMetadata instances
             populated by the parsed
            annotations, yaml, xml, etc.


Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                                              Query Cache



 $config->setQueryCacheImpl(new DoctrineCommonCacheApcCache);




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




 In production cache the parsing
 of a DQL query and the final SQL
           generated.



Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                                             Result Cache



$config->setResultCacheImpl(new DoctrineCommonCacheApcCache);




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




In production cache the hydrated
  data of your queries to avoid
   unnecessary queries to the
            database.


Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                               Using Result Cache
               $query = $em->createQuery('SELECT u FROM ModelsUser u')
               $query->useResultCache(true, 3600, 'user_query');
               $users = $query->execute();




Execute it again and it pulls the results from
 the cache instead of hitting the database

               $users = $query->execute();




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                               Using Result Cache                                        The parsing of this
                                                                                      query will only ever happen
                                                                                      once with the query cache
                                                                                       configured.

               $query = $em->createQuery('SELECT u FROM ModelsUser u')
               $query->useResultCache(true, 3600, 'user_query');
               $users = $query->execute();




Execute it again and it pulls the results from
 the cache instead of hitting the database

               $users = $query->execute();




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




             Inheritance Mapping



Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                          Mapped Superclasses




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




       /** @MappedSuperclass */
       abstract class MappedSuperclassBase
       {
           /** @Column(type="integer") */
           private $mapped1;

               /** @Column(type="string") */
               private $mapped2;

               /**
                * @OneToOne(targetEntity="MappedSuperclassRelated1")
                * @JoinColumn(name="related1_id", referencedColumnName="id")
                */
               private $mappedRelated1;

               // ... more fields and methods
       }




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                         Extend the Superclass




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                       /** @Entity */
                       class EntitySubClass extends MappedSuperclassBase
                       {
                           /** @Id @Column(type="integer") */
                           private $id;
                           /** @Column(type="string") */
                           private $name;

                                // ... more fields and methods
                       }




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                     Single Table Inheritance




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                   /**
                     * @Entity
                     * @InheritanceType("SINGLE_TABLE")
                     * @DiscriminatorColumn(name="discriminator", type="string")
                     * @DiscriminatorMap({"person" = "Person", "employee" = "Employee"})
                     */
                   class Person
                   {
                        // ...
                   }

                   /**
                     * @Entity
                     */
                   class Employee extends Person
                   {
                        // ...
                   }




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                                               Single Table
  • All classes of a hierarchy are mapped to a
    single table

  • Discriminator column used to distinguish
    type of a row in the database

  • Efficient for querying across all types in the
    hierarchy or for specific types.

  • Queries limited by type discriminator
Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                      Class Table Inheritance




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                   /**
                     * @Entity
                     * @InheritanceType("JOINED")
                     * @DiscriminatorColumn(name="discr", type="string")
                     * @DiscriminatorMap({"person" = "Person", "employee" = "Employee"})
                     */
                   class Person
                   {
                        // ...
                   }

                   /** @Entity */
                   class Employee extends Person
                   {
                       // ...
                   }




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                                                Class Table
  • Each class in a hierarchy is mapped to
    several tables

  • Table of a child class is linked to the table
    of a parent class

  • Discriminator column used to distinguish
    type of a row in the database

  • Queries almost always require joins
Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                                                 Testing


Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                    PHPUnit for Unit Testing




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                      bambino:tests jwage$ phpunit Doctrine/Tests/AllTests.php
                      PHPUnit 3.3.17 by Sebastian Bergmann.

                      ...............................................S.SS.........         60   /   673
                      ............................................................        120   /   673
                      ............................................................        180   /   673
                      ...SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS....................        240   /   673
                      ............................................................        300   /   673
                      ............................................................        360   /   673
                      ............................................................        420   /   673
                      ............................................................        480   /   673
                      ............................................................        540   /   673
                      ............................................................        600   /   673
                      .................SSSS.....................SS.S......S..SS.S.        660   /   673
                      .....S..SS.S.

                      Time: 3 seconds

                      OK, but incomplete or skipped tests!
                      Tests: 673, Assertions: 1771, Skipped: 55.




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




Sismo for Continuous Integration




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                               Growl Notifications




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




       Sismo keeps a close eye on all of our
    projects. We even run the Doctrine 2 tests
      against multiple supported databases.




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                          Custom Types


Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com



                    namespace DoctrineDBALTypes;

                    class MyCustomObjectType extends Type
                    {
                        public function getName()
                        {
                            return 'MyCustomObjectType';
                        }

                           public function getSqlDeclaration(array $fieldDeclaration,
                           DoctrineDBALPlatformsAbstractPlatform $platform)
                           {
                               return $platform->getClobDeclarationSql($fieldDeclaration);
                           }

                           public function convertToDatabaseValue($value,
                           DoctrineDBALPlatformsAbstractPlatform $platform)
                           {
                               return serialize($value);
                           }

                           public function convertToPHPValue($value)
                           {
                               return unserialize($value);
                           }
                    }


Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                              Type::addCustomType(
                                 'MyCustomObjectType',
                                 'DoctrineDBALTypesMyCustomObjectType'
                              );




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                        Override Types


Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




           class MyString extends StringType
           {

           }

           Type::overrideType('string', 'DoctrineDBALTypesMyString');




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3     www.doctrine-project.org   www.sensiolabs.com




                                                        Thanks!!




Big Lamp Camp 2009                   #eLAMP
Doctrine 2: Enterprise Persistence Layer for PHP 5.3   www.doctrine-project.org   www.sensiolabs.com




                       Jonathan H. Wage
                       jonathan.wage@sensio.com
                       +1 415 992 5468

                       sensiolabs.com | doctrine-project.org | sympalphp.org | jwage.com



           You can contact Jonathan about Doctrine and Open-Source or
            for training, consulting, application development, or business
                   related questions at jonathan.wage@sensio.com




Big Lamp Camp 2009                   #eLAMP

Doctrine 2: Enterprise Persistence Layer for PHP

  • 1.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Doctrine 2 Enterprise Persistence Layer for PHP 5.3 Big Lamp Camp 2009 #eLAMP
  • 2.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Jonathan H. Wage • Web developer for a decade • Open Source Evangelist • Published Author • Contributes to... • ...Doctrine • ...Symfony • ...and more • Employee of Sensio Labs, the creators of Symfony Big Lamp Camp 2009 #eLAMP
  • 3.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Jonathan H. Wage • http://www.twitter.com/jwage • http://www.jwage.com • http://www.facebook.com/jwage You can contact Jonathan about Doctrine and Open-Source or for training, consulting, application development, or business related questions at jonathan.wage@sensio.com Big Lamp Camp 2009 #eLAMP
  • 4.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com How many have used Doctrine? • Before 1.0? • 1.0? • 1.1? • 1.2? • 2.0? Big Lamp Camp 2009 #eLAMP
  • 5.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Doctrine 1.0 • First commit April 13th 2006 • Finished and Released September 1st 2008 • One of the first true ORM implementation for PHP • First LTS(long term support) release. Maintained until March 1st 2010 • Integrated with many popular frameworks: Symfony, Zend Framework, Code Igniter, etc. Big Lamp Camp 2009 #eLAMP
  • 6.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Doctrine 1.1 • Continued evolution of 1.0 • Dozens of small improvements • Several significant new features • Too many bug fixes to count Big Lamp Camp 2009 #eLAMP
  • 7.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Doctrine 1.2 • Last LTS release of the Doctrine 1.x series • More bug fixes • More improvements • Even more new features • Scheduled to release this month Big Lamp Camp 2009 #eLAMP
  • 8.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Doctrine 2.0 Big Lamp Camp 2009 #eLAMP
  • 9.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Requires PHP 5.3 Big Lamp Camp 2009 #eLAMP
  • 10.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Three Main Packages Big Lamp Camp 2009 #eLAMP
  • 11.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Common Big Lamp Camp 2009 #eLAMP
  • 12.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com DBAL Big Lamp Camp 2009 #eLAMP
  • 13.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com ORM Big Lamp Camp 2009 #eLAMP
  • 14.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Fully implements namespaces Big Lamp Camp 2009 #eLAMP
  • 15.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Namespaced Code namespace DoctrineORM; use DoctrineORMQueryExpr, DoctrineCommonDoctrineException; /** * This class is responsible for building DQL query strings via an object oriented * PHP interface. * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.doctrine-project.org * @since 2.0 * @version $Revision$ * @author Guilherme Blanco <guilhermeblanco@hotmail.com> * @author Jonathan Wage <jonwage@gmail.com> * @author Roman Borschel <roman@code-factory.org> */ class QueryBuilder { Big Lamp Camp 2009 #eLAMP
  • 16.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Using Namespaces use DoctrineORMQueryBuilder; $qb = new QueryBuilder($em); $qb->select('u') ->from('ModelsUser', 'u') ->orderBy('u.username', 'ASC'); $q = $qb->getQuery(); $users = $q->execute(); Big Lamp Camp 2009 #eLAMP
  • 17.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Follows PHP 5.3 technical interoperability standards http://groups.google.com/group/php-standards/web/php-coding-standard-version-2 Big Lamp Camp 2009 #eLAMP
  • 18.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com What does this mean? • PHP libraries will finally be 100% technically interoperable and have optimum autoloading performance • Symfony 2.0 + Doctrine 2.0 + Zend Framework 2.0 • Load classes from 3 different libraries with one autoloader and one include path • Share SplClassLoader implementation: http:// gist.github.com/221634 • Implement SplClassLoader in C/PHP :) Big Lamp Camp 2009 #eLAMP
  • 19.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Performance of PHP 5.3 Big Lamp Camp 2009 #eLAMP
  • 20.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Doctrine 1 and 2 get significant performance increase from 5.3 Big Lamp Camp 2009 #eLAMP
  • 21.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com 30% Less Memory Used Big Lamp Camp 2009 #eLAMP
  • 22.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com 20% Faster Big Lamp Camp 2009 #eLAMP
  • 23.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com What’s my point? USE PHP 5.3! Big Lamp Camp 2009 #eLAMP
  • 24.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Let the numbers talk Doctrine 1.1 4.3 seconds for 5000 records Doctrine 2.0 1.4 seconds for 5000 records Doctrine 2.0 3.5 seconds for 10000 records Big Lamp Camp 2009 #eLAMP
  • 25.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Doctrine 2 is FAST! Big Lamp Camp 2009 #eLAMP
  • 26.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com The code isn’t that bad on the eyes either Big Lamp Camp 2009 #eLAMP
  • 27.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Quit imposing on my domain model!! Big Lamp Camp 2009 #eLAMP
  • 28.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com The Doctrine 1 Way class User extends Doctrine_Record { public function setTableDefinition() { $this->hasColumn('id', 'integer', null, array( 'primary' => true, 'auto_increment' => true )); $this->hasColumn('username', 'string', 255); } } Big Lamp Camp 2009 #eLAMP
  • 29.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com What is the problem? • We have to extend Doctrine_Record • It imposes methods, properties, and other junk on our domain model objects • We have to instantiate a dummy User in order to instantiate the metadata for the model • Slow, ugly and just not pretty :) Big Lamp Camp 2009 #eLAMP
  • 30.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com The new Doctrine 2 Way Specify mapping information with doc block annotations, yaml, xml, or raw PHP code. Big Lamp Camp 2009 #eLAMP
  • 31.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com With Annotations /** * @Entity * @Table(name="user") */ class User { /** * @Id * @Column(type="integer") * @GeneratedValue(strategy="auto") */ public $id; /** * @Column(type="string", length=255) */ public $username; } Big Lamp Camp 2009 #eLAMP
  • 32.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com With YAML EntitiesUser: type: entity table: users fields: id: type: integer id: true generator: strategy: AUTO name: type: string(50) Big Lamp Camp 2009 #eLAMP
  • 33.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com With XML <?xml version="1.0" encoding="utf-8"?> <doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xsi="http:// www.w3.org/2001/XMLSchema-instance" schemaLocation="http://doctrine-project.org/schemas/orm/ doctrine-mapping.xsd"> <entity name="EntitiesUser" table="users"> <field name="name" type="string" column="name" length="50" precision="0" scale="0"> <options/> </field> <id name="id" type="integer" column="id"> <generator strategy="AUTO"/> </id> </entity> </doctrine-mapping> Big Lamp Camp 2009 #eLAMP
  • 34.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com With PHP use DoctrineORMMappingClassMetadataInfo; $metadata->setInheritanceType(ClassMetadataInfo::INHERITANCE_TYPE_NONE); $metadata->setPrimaryTable(array( 'name' => 'users', )); $metadata->mapField(array( 'fieldName' => 'id', 'type' => 'integer', 'id' => true, 'columnName' => 'id', )); $metadata->mapField(array( 'fieldName' => 'name', 'type' => 'string', 'length' => '50', 'columnName' => 'name', )); $metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_AUTO); Big Lamp Camp 2009 #eLAMP
  • 35.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com No more base class... $user = new EntitiesUser(); $user->setUsername('jwage'); print_r($user); User Object ( [id] => [username] => jwage ) ...means a clean domain model Big Lamp Camp 2009 #eLAMP
  • 36.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Doctrine 2 is heavily decoupled so you can use things standalone Big Lamp Camp 2009 #eLAMP
  • 37.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Use the DBAL without the ORM! Big Lamp Camp 2009 #eLAMP
  • 38.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Database Abstraction Layer • The Doctrine DBAL is a very powerful project in itself • Based off of code borrowed from other projects • PEAR MDB2 • Zend_Db Big Lamp Camp 2009 #eLAMP
  • 39.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Database Abstraction Layer • Using the Doctrine DBAL standalone is a good option for your PHP projects if a fully featured ORM is not needed • API for performing DDL statements, executing queries, etc. • Connect to different types of databases: mysql, sqlite, pgsql, oracle, etc. Big Lamp Camp 2009 #eLAMP
  • 40.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com DBAL Examples Big Lamp Camp 2009 #eLAMP
  • 41.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Create a Connection to MySQL $params = array( 'driver' => 'pdo_mysql', 'host' => 'localhost', 'user' => 'root', 'password' => '', 'dbname' => 'doctrine2dbal' ); $conn = DoctrineDBALDriverManager::getConnection($params); Big Lamp Camp 2009 #eLAMP
  • 42.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Get the Schema Manager $sm = $conn->getSchemaManager(); Big Lamp Camp 2009 #eLAMP
  • 43.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Schema Manager • Issue DDL statements through intuitive API: createTable(), dropTable(), createForeignKey(), etc. • Introspect your database schema as well: listTables(), listTableColumns(), listUsers(), etc. Big Lamp Camp 2009 #eLAMP
  • 44.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Drop and Create a Table $columns = array( 'id' => array( 'type' => Type::getType('integer'), 'autoincrement' => true, 'primary' => true, 'notnull' => true ), 'name' => array( 'type' => Type::getType('string'), 'length' => 255 ), ); $sm->dropAndCreateTable('user', $columns); Big Lamp Camp 2009 #eLAMP
  • 45.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Create a Foreign Key $definition = array( 'name' => 'user_id_fk', 'local' => 'user_id', 'foreign' => 'id', 'foreignTable' => 'user' ); $sm->createForeignKey('profile', $definition); Big Lamp Camp 2009 #eLAMP
  • 46.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com So much more... • Fully featured DBAL for manipulating your database with DDL statements • Introspect your database and learn about it • Execute queries and retrieve data • Support for transactions Big Lamp Camp 2009 #eLAMP
  • 47.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com The ORM Key Feature Big Lamp Camp 2009 #eLAMP
  • 48.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Doctrine Query Language Big Lamp Camp 2009 #eLAMP
  • 49.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com DQL stands for Doctrine Query Language and is heavily influenced by HQL from Hibernate Big Lamp Camp 2009 #eLAMP
  • 50.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Proprietary OQL(object query language) dialect Big Lamp Camp 2009 #eLAMP
  • 51.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com The DQL is parsed by a hand written recursive descent parser Big Lamp Camp 2009 #eLAMP
  • 52.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Constructs AST Big Lamp Camp 2009 #eLAMP
  • 53.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com AST = Abstract Syntax Tree Big Lamp Camp 2009 #eLAMP
  • 54.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Tree representation of the syntactic structure of a source language Big Lamp Camp 2009 #eLAMP
  • 55.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com PHP class names of DQL parser directly represent the language itself OrderByClause.php SelectClause.php SelectExpression.php Subselect.php DeleteClause.php etc. etc. Big Lamp Camp 2009 #eLAMP
  • 56.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Every DQL feature has a class to handle the parsing Big Lamp Camp 2009 #eLAMP
  • 57.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com • Easy to use • Easy to expand and add new features • Easy to use and understand the parsing of a DQL string • Expand the DQL parser with your own functionality and add to the DQL language Big Lamp Camp 2009 #eLAMP
  • 58.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com DQL parser is very fast as it is. With final SQL caching it becomes invisible. Big Lamp Camp 2009 #eLAMP
  • 59.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Sample DQL Query $query = $em->createQuery( 'SELECT u, g, FROM User u ' . 'LEFT JOIN u.Groups g ' . 'ORDER BY u.name ASC, g.name ASC' ); $users = $query->execute(); Big Lamp Camp 2009 #eLAMP
  • 60.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Using the QueryBuilder $qb = $em->createQueryBuilder() ->select('u, g') ->from('User', 'u') ->leftJoin('u.Groups', 'g') ->orderBy('u.name', 'ASC') ->addOrderBy('g.name', 'ASC'); $query = $qb->getQuery(); Big Lamp Camp 2009 #eLAMP
  • 61.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Executing Queries $users = $query->execute(); foreach ($users as $user) { // ... foreach ($user->getGroups() as $group) { // ... } } Big Lamp Camp 2009 #eLAMP
  • 62.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Working with Entities Big Lamp Camp 2009 #eLAMP
  • 63.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com The EntityManager Big Lamp Camp 2009 #eLAMP
  • 64.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com The EntityManager is responsible for managing the persistence of entities Big Lamp Camp 2009 #eLAMP
  • 65.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Creating the EntityManager $config = new DoctrineORMConfiguration(); $config->setMetadataCacheImpl(new DoctrineCommonCacheArrayCache); $config->setProxyDir(__DIR__ . '/Proxies'); $config->setProxyNamespace('Proxies'); $connectionOptions = array( 'driver' => 'pdo_sqlite', 'path' => 'database.sqlite' ); $em = DoctrineORMEntityManager::create($connectionOptions, $config); Big Lamp Camp 2009 #eLAMP
  • 66.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Persisting Entities $user = new User; $user->setUsername('jwage'); $user->setPassword('changeme'); $profile = new Profile; $profile->setName('Jonathan H. Wage'); $user->setProfile($user); $em->persist($user); $em->persist($profile); $em->flush(); Big Lamp Camp 2009 #eLAMP
  • 67.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Deleting Entities $user1 = $em->find('User', 1); $user2 = $em->find('User', 2); $em->remove($user1); $em->remove($user2); $em->flush(); Big Lamp Camp 2009 #eLAMP
  • 68.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com EntityManager::flush() • Commits any changes to the managed entities • Efficiently executes insert, update and delete statements • Keep number of flush() operations down to about 1-2 times per request Big Lamp Camp 2009 #eLAMP
  • 69.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com The EntityManager::flush() operation is able to insert, update and delete entities very efficiently. It is ideal to keep your flush operations to about 1-2 times per request Big Lamp Camp 2009 #eLAMP
  • 70.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Metadata Cache $config = new DoctrineORMConfiguration(); $config->setMetadataCacheImpl(new DoctrineCommonCacheApcCache); Big Lamp Camp 2009 #eLAMP
  • 71.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com In production cache the ClassMetadata instances populated by the parsed annotations, yaml, xml, etc. Big Lamp Camp 2009 #eLAMP
  • 72.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Query Cache $config->setQueryCacheImpl(new DoctrineCommonCacheApcCache); Big Lamp Camp 2009 #eLAMP
  • 73.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com In production cache the parsing of a DQL query and the final SQL generated. Big Lamp Camp 2009 #eLAMP
  • 74.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Result Cache $config->setResultCacheImpl(new DoctrineCommonCacheApcCache); Big Lamp Camp 2009 #eLAMP
  • 75.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com In production cache the hydrated data of your queries to avoid unnecessary queries to the database. Big Lamp Camp 2009 #eLAMP
  • 76.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Using Result Cache $query = $em->createQuery('SELECT u FROM ModelsUser u') $query->useResultCache(true, 3600, 'user_query'); $users = $query->execute(); Execute it again and it pulls the results from the cache instead of hitting the database $users = $query->execute(); Big Lamp Camp 2009 #eLAMP
  • 77.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Using Result Cache The parsing of this query will only ever happen once with the query cache configured. $query = $em->createQuery('SELECT u FROM ModelsUser u') $query->useResultCache(true, 3600, 'user_query'); $users = $query->execute(); Execute it again and it pulls the results from the cache instead of hitting the database $users = $query->execute(); Big Lamp Camp 2009 #eLAMP
  • 78.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Inheritance Mapping Big Lamp Camp 2009 #eLAMP
  • 79.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Mapped Superclasses Big Lamp Camp 2009 #eLAMP
  • 80.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com /** @MappedSuperclass */ abstract class MappedSuperclassBase { /** @Column(type="integer") */ private $mapped1; /** @Column(type="string") */ private $mapped2; /** * @OneToOne(targetEntity="MappedSuperclassRelated1") * @JoinColumn(name="related1_id", referencedColumnName="id") */ private $mappedRelated1; // ... more fields and methods } Big Lamp Camp 2009 #eLAMP
  • 81.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Extend the Superclass Big Lamp Camp 2009 #eLAMP
  • 82.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com /** @Entity */ class EntitySubClass extends MappedSuperclassBase { /** @Id @Column(type="integer") */ private $id; /** @Column(type="string") */ private $name; // ... more fields and methods } Big Lamp Camp 2009 #eLAMP
  • 83.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Single Table Inheritance Big Lamp Camp 2009 #eLAMP
  • 84.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com /** * @Entity * @InheritanceType("SINGLE_TABLE") * @DiscriminatorColumn(name="discriminator", type="string") * @DiscriminatorMap({"person" = "Person", "employee" = "Employee"}) */ class Person { // ... } /** * @Entity */ class Employee extends Person { // ... } Big Lamp Camp 2009 #eLAMP
  • 85.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Single Table • All classes of a hierarchy are mapped to a single table • Discriminator column used to distinguish type of a row in the database • Efficient for querying across all types in the hierarchy or for specific types. • Queries limited by type discriminator Big Lamp Camp 2009 #eLAMP
  • 86.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Class Table Inheritance Big Lamp Camp 2009 #eLAMP
  • 87.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com /** * @Entity * @InheritanceType("JOINED") * @DiscriminatorColumn(name="discr", type="string") * @DiscriminatorMap({"person" = "Person", "employee" = "Employee"}) */ class Person { // ... } /** @Entity */ class Employee extends Person { // ... } Big Lamp Camp 2009 #eLAMP
  • 88.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Class Table • Each class in a hierarchy is mapped to several tables • Table of a child class is linked to the table of a parent class • Discriminator column used to distinguish type of a row in the database • Queries almost always require joins Big Lamp Camp 2009 #eLAMP
  • 89.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Testing Big Lamp Camp 2009 #eLAMP
  • 90.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com PHPUnit for Unit Testing Big Lamp Camp 2009 #eLAMP
  • 91.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com bambino:tests jwage$ phpunit Doctrine/Tests/AllTests.php PHPUnit 3.3.17 by Sebastian Bergmann. ...............................................S.SS......... 60 / 673 ............................................................ 120 / 673 ............................................................ 180 / 673 ...SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS.................... 240 / 673 ............................................................ 300 / 673 ............................................................ 360 / 673 ............................................................ 420 / 673 ............................................................ 480 / 673 ............................................................ 540 / 673 ............................................................ 600 / 673 .................SSSS.....................SS.S......S..SS.S. 660 / 673 .....S..SS.S. Time: 3 seconds OK, but incomplete or skipped tests! Tests: 673, Assertions: 1771, Skipped: 55. Big Lamp Camp 2009 #eLAMP
  • 92.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Sismo for Continuous Integration Big Lamp Camp 2009 #eLAMP
  • 93.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Big Lamp Camp 2009 #eLAMP
  • 94.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Big Lamp Camp 2009 #eLAMP
  • 95.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Growl Notifications Big Lamp Camp 2009 #eLAMP
  • 96.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Sismo keeps a close eye on all of our projects. We even run the Doctrine 2 tests against multiple supported databases. Big Lamp Camp 2009 #eLAMP
  • 97.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Custom Types Big Lamp Camp 2009 #eLAMP
  • 98.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com namespace DoctrineDBALTypes; class MyCustomObjectType extends Type { public function getName() { return 'MyCustomObjectType'; } public function getSqlDeclaration(array $fieldDeclaration, DoctrineDBALPlatformsAbstractPlatform $platform) { return $platform->getClobDeclarationSql($fieldDeclaration); } public function convertToDatabaseValue($value, DoctrineDBALPlatformsAbstractPlatform $platform) { return serialize($value); } public function convertToPHPValue($value) { return unserialize($value); } } Big Lamp Camp 2009 #eLAMP
  • 99.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Type::addCustomType( 'MyCustomObjectType', 'DoctrineDBALTypesMyCustomObjectType' ); Big Lamp Camp 2009 #eLAMP
  • 100.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Override Types Big Lamp Camp 2009 #eLAMP
  • 101.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com class MyString extends StringType { } Type::overrideType('string', 'DoctrineDBALTypesMyString'); Big Lamp Camp 2009 #eLAMP
  • 102.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Thanks!! Big Lamp Camp 2009 #eLAMP
  • 103.
    Doctrine 2: EnterprisePersistence Layer for PHP 5.3 www.doctrine-project.org www.sensiolabs.com Jonathan H. Wage jonathan.wage@sensio.com +1 415 992 5468 sensiolabs.com | doctrine-project.org | sympalphp.org | jwage.com You can contact Jonathan about Doctrine and Open-Source or for training, consulting, application development, or business related questions at jonathan.wage@sensio.com Big Lamp Camp 2009 #eLAMP