SlideShare a Scribd company logo
1 of 94
Download to read offline
#sflive2010




               Doctrine 2
             Not the same Old PHP ORM



Doctrine 2     www.doctrine-project.org   www.sensiolabs.com
#sflive2010




    What is different in Doctrine 2?




Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010




             New code, new concepts,
                different workļ¬‚ow




Doctrine 2    www.doctrine-project.org   www.sensiolabs.com
#sflive2010




       100% re-written codebase for
                PHP 5.3




Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010




                         Are you scared?




Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010




         You shouldnā€™t be! It is a very
          exciting thing for PHP and
           change is a good thing!



Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010




We learned lots building Doctrine
 1 and we used that to help us
        build Doctrine 2



Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010




               Let me tell you why!




Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010

             Performance of Doctrine 1



                     To hydrate 5000 records
                       in Doctrine 1 it takes
                      roughly 4.3 seconds.




Doctrine 2     www.doctrine-project.org   www.sensiolabs.com
#sflive2010

             Performance of Doctrine 2



                Under Doctrine 2, hydrating
              those same 5000 records only
                    takes 1.4 seconds.




Doctrine 2     www.doctrine-project.org   www.sensiolabs.com
#sflive2010

             Performance of Doctrine 2


              ...and with 10000 records it still
               only takes about 3.5 seconds.

               Twice the data and still faster
                      than Doctrine 1



Doctrine 2     www.doctrine-project.org   www.sensiolabs.com
#sflive2010

             Performance of Doctrine 2
ā€¢ More interesting than the numbers
  themselves is the percentage improvement
  over Doctrine 1




Doctrine 2     www.doctrine-project.org   www.sensiolabs.com
#sflive2010

                         Why is it faster?
ā€¢ PHP 5.3 gives us a huge performance
  improvement when using a heavily OO
  framework like Doctrine
ā€¢ Better optimized hydration algorithm
ā€¢ New query and result caching
  implementations
ā€¢ All around more explicit and less magical
  code results in better and faster code.
ā€¢ Killed the magical aspect of Doctrine 1


Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010

                 Why kill the magic?
ā€¢ Eliminate the WTF? factor of Doctrine 1




Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010




             The Doctrine 1 magical
               features are both a
              blessing and a curse

Doctrine 2     www.doctrine-project.org   www.sensiolabs.com
#sflive2010

             Blessing and a Curse
ā€¢ Magic is great when it works
ā€¢ The magic you love is also the cause of all
  the pain youā€™ve felt with Doctrine 1
ā€¢ When it doesnā€™t work it is hard to debug
ā€¢ Edge cases are hard to ļ¬x
ā€¢ Edge cases are hard to work around
ā€¢ Edge cases, edge cases, edge cases
ā€¢ Everything is okay until you try and go
  outside the box the magic provides
ā€¢ ...magic is slow
Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010

    How will we replace the magic?
      This new thing called OOP :)

ā€¢    Object Composition
ā€¢    Inheritance
ā€¢    Aggregation
ā€¢    Containment
ā€¢    Encapsulation
ā€¢    ...etc


Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010

   Will Doctrine 2 have behaviors?




                             Yes and No



Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010

                                        The No
ā€¢ We wonā€™t have any concept of ā€œmodel
  behaviorsā€

ā€¢ Behaviors were a made up concept for
  Doctrine 1 to work with its extremely
  intrusive architecture.

ā€¢ It tries to do things that PHP does not allow
  and is the result of lots of problems in
  Doctrine 1
Doctrine 2   www.doctrine-project.org      www.sensiolabs.com
#sflive2010

                                        The Yes
ā€¢ Everything you can do in Doctrine 1 you can
  do in Doctrine 2, just in a different way.

ā€¢ ā€œBehaviorā€ like functionality will be bundled
  as extensions for Doctrine 2 and will just
  contain normal OO PHP code that wraps/
  extends Doctrine code or is meant to be
  wrapped or extended by your entities.



Doctrine 2   www.doctrine-project.org       www.sensiolabs.com
#sflive2010




             What did we use to build
                   Doctrine 2?




Doctrine 2    www.doctrine-project.org   www.sensiolabs.com
#sflive2010

               Doctrine 2 Tool Belt
ā€¢    phpUnit 3.4.10 - Unit Testing
ā€¢    Phing - Packaging and Distribution
ā€¢    Symfony YAML Component
ā€¢    Sismo - Continuous Integration
ā€¢    Subversion - Source Control
ā€¢    Jira - Issue Tracking and Management
ā€¢    Trac - Subversion Timeline, Source Code
     Browser, Changeset Viewer


Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010

             Doctrine 2 Architecture
ā€¢ Entities
ā€¢ Lightweight persistent domain object
ā€¢ Regular PHP class
ā€¢ Does not extend any base Doctrine class
ā€¢ Cannot be ļ¬nal or contain ļ¬nal methods
ā€¢ Any two entities in a hierarchy of classes must not have a
  mapped property with the same name
ā€¢ Supports inheritance, polymorphic associations and
  polymorphic queries.
ā€¢ Both abstract and concrete classes can be entities
ā€¢ Entities may extend non-entity classes as well as entity
  classes, and non-entity classes may extend entity classes


Doctrine 2    www.doctrine-project.org   www.sensiolabs.com
#sflive2010

             Doctrine 2 Architecture
ā€¢ Your entities in Doctrine 2 donā€™t require
  that you extend a base class like in Doctrine
  1! No more imposing on your domain
  model!
                                namespace Entities;

                                class User
                                {
                                    private $id;
                                    private $name;
                                    private $address;
                                }

Doctrine 2    www.doctrine-project.org     www.sensiolabs.com
#sflive2010

             Doctrine 2 Architecture
ā€¢ The EntityManager
ā€¢ Central access point to the ORM functionality provided by
  Doctrine 2. API is used to manage the persistence of your
  objects and to query for persistent objects.
ā€¢ Employes transactional write behind strategy that delays the
  execution of SQL statements in order to execute them in the
  most efficient way
ā€¢ Execute at end of transaction so that all write locks are quickly
  releases
ā€¢ Internally an EntityManager uses a UnitOfWork to keep track
  of your objects




Doctrine 2    www.doctrine-project.org   www.sensiolabs.com
#sflive2010

                                 Unit Testing
ā€¢ Tests are ran against multiple DBMS types.
  This is something that was not possible
  with the Doctrine 1 test suite.

ā€¢    ...Sqlite
ā€¢    ...MySQL
ā€¢    ...Oracle
ā€¢    ...PgSQL
ā€¢    ...more to come

Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010

                                 Unit Testing
ā€¢ 859 Test Cases
ā€¢ 2152 Assertions
ā€¢ Tests run in a few seconds compared to
  30-40 seconds for Doctrine 1
ā€¢ Much more granular and explicit unit tests
ā€¢ Easier to debug failed tests
ā€¢ Continuously integrated by Sismo :)




Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010

                                         Sismo
      ā€“ No, Sismo is not available yet!!!!!!!!! :)
      ā€“ Want it? Bug Fabien!




Doctrine 2    www.doctrine-project.org      www.sensiolabs.com
#sflive2010

             Database Abstraction Layer
ā€¢ Separate standalone package and
  namespace (DoctrineDBAL).

ā€¢ Can be used standalone.

ā€¢ Much improved over Doctrine 1 in regards
  to the API for database introspection and
  schema management.



Doctrine 2     www.doctrine-project.org   www.sensiolabs.com
#sflive2010

             Database Abstraction Layer
ā€¢ Hopefully Doctrine 2 DBAL can be the
  defacto standard DBAL for PHP 5.3 in the
  future like MDB and MDB2 were in PEAR

ā€¢ Maybe we can make this happen for PEAR2?




Doctrine 2     www.doctrine-project.org   www.sensiolabs.com
#sflive2010

                                DBAL Data API
ā€¢    prepare($sql) - Prepare a given sql statement and return the DoctrineDBAL
     DriverStatement instance.
ā€¢    executeUpdate($sql, array $params) - Executes a prepared statement with the
     given sql and parameters and returns the affected rows count.
ā€¢    execute($sql, array $params) - Creates a prepared statement for the given sql and
     passes the parameters to the execute method, then returning the statement.
ā€¢    fetchAll($sql, array $params) - Execute the query and fetch all results into an array.
ā€¢    fetchArray($sql, array $params) - Numeric index retrieval of ļ¬rst result row of the
     given query.
ā€¢    fetchBoth($sql, array $params) - Both numeric and assoc column name retrieval of
     the ļ¬rst result row.
ā€¢    fetchColumn($sql, array $params, $colnum) - Retrieve only the given column of
     the ļ¬rst result row.
ā€¢    fetchRow($sql, array $params) - Retrieve assoc row of the ļ¬rst result row.
ā€¢    select($sql, $limit, $offset) - Modify the given query with a limit clause.
ā€¢    delete($tableName, array $identiļ¬er) - Delete all rows of a table matching the
     given identiļ¬er, where keys are column names.
ā€¢    insert($tableName, array $data) - Insert a row into the given table name using the

Doctrine 2       www.doctrine-project.org        www.sensiolabs.com
#sflive2010

             DBAL Introspection API
ā€¢    listDatabases()
ā€¢    listFunctions()
ā€¢    listSequences()
ā€¢    listTableColumns($tableName)
ā€¢    listTableConstraints($tableName)
ā€¢    listTableDetails($tableName)
ā€¢    listTableForeignKeys($tableName)
ā€¢    listTableIndexes($tableName)
ā€¢    listTables()
Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010

        DBAL Schema Representation
$schema = new DoctrineDBALSchemaSchema();
$myTable = $schema->createTable("my_table");
$myTable->createColumn("id", "integer", array("unsigned" => true));
$myTable->createColumn("username", "string", array("length" => 32));
$myTable->setPrimaryKey(array("id"));
$myTable->addUniqueIndex(array("username"));
$schema->createSequence("my_table_seq");

$myForeign = $schema->createTable("my_foreign");
$myForeign->createColumn("id", "integer");
$myForeign->createColumn("user_id", "integer");
$myForeign->addForeignKeyConstraint($myTable, array("user_id"),
array("id"), array("onUpdate" => "CASCADE"));

$queries = $schema->toSql($myPlatform); // get queries to create this
schema.
$dropSchema = $schema->toDropSql($myPlatform); // get queries to
safely delete this schema.

Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010

                Compare DBAL Schemas


             $comparator = new DoctrineDBALSchemaComparator();
             $schemaDiff = $comparator->compare($fromSchema, $toSchema);

             // queries to get from one to another schema.
             $queries = $schemaDiff->toSql($myPlatform);
             $saveQueries = $schemaDiff->toSaveSql($myPlatform);




Doctrine 2         www.doctrine-project.org   www.sensiolabs.com
#sflive2010

             Schema Management
ā€¢ Extracted from ORM to DBAL

ā€¢ Schema comparisons replace the migrations
  diff tool of Doctrine 1




Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010

             Doctrine 2 Annotations
                    <?php

                    namespace Entities;

                    /**
                      * @Entity @Table(name="users")
                      */
                    class User
                    {
                         /** @Id @Column(type="integer") @GeneratedValue */
                         private $id;

                          /** @Column(length=50) */
                          private $name;

                          /** @OneToOne(targetEntity="Address") */
                          private $address;
                    }




Doctrine 2   www.doctrine-project.org                 www.sensiolabs.com
#sflive2010

                       Things to Notice
ā€¢ Entities no longer require you to extend a
  base class!
ā€¢ Your domain model has absolutely no
  magic, is not imposed on by Doctrine and is
  deļ¬ned by raw PHP objects and normal OO
  programming.
ā€¢ The performance improvement from this is
  signiļ¬cant.
ā€¢ Easier to understand what is happening due
  to less magic occurring. As Fabien says,
  ā€œKill the magic...ā€
Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010

                       Doctrine 2 YAML
                                    EntitiesAddress:
                                      type: entity
                                      table: addresses
                                      id:
                                        id:
                                          type: integer
                                          generator:
                                            strategy: AUTO
                                      fields:
                                        street:
                                          type: string
                                          length: 255
                                      oneToOne:
                                        user:
                                          targetEntity: User
                                          mappedBy: address



Doctrine 2   www.doctrine-project.org            www.sensiolabs.com
#sflive2010

                              Doctrine 2 XML
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
                    http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">

     <entity name="EntitiesUser" table="users">
         <id name="id" type="integer">
             <generator strategy="AUTO"/>
         </id>
         <field name="name" type="string" length="50"/>
         <one-to-one field="address" target-entity="Address">
             <join-column name="address_id" referenced-column-name="id"/>
         </one-to-one>
     </entity>

</doctrine-mapping>




Doctrine 2       www.doctrine-project.org       www.sensiolabs.com
#sflive2010

                       Doctrine 2 Setup
ā€¢ PHP ā€œuseā€ all necessary namespaces and
  classes

             use DoctrineCommonClassLoader,
                 DoctrineORMConfiguration,
                 DoctrineORMEntityManager,
                 DoctrineCommonCacheApcCache,
                 EntitiesUser, EntitiesAddress;




Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010

                       Doctrine 2 Setup
ā€¢ Require the Doctrine ClassLoader



 require '../../lib/Doctrine/Common/ClassLoader.php';




Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010

                       Doctrine 2 Setup
ā€¢ Setup autoloading for Doctrine classes
ā€¢ ...core classes
ā€¢ ...entity classes
ā€¢ ...proxy classes

$doctrineClassLoader = new ClassLoader('Doctrine', '/path/to/doctrine');
$doctrineClassLoader->register();

$entitiesClassLoader = new ClassLoader('Entities', '/path/to/entities');
$entitiesClassLoader->register();

$proxiesClassLoader = new ClassLoader('Proxies', '/path/to/proxies');
$proxiesClassLoader->register();



Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010

                       Doctrine 2 Setup
ā€¢ Conļ¬gure your Doctrine implementation

               // Set up caches
               $config = new Configuration;
               $cache = new ApcCache;
               $config->setMetadataCacheImpl($cache);
               $config->setQueryCacheImpl($cache);

               // Proxy configuration
               $config->setProxyDir('/path/to/proxies/Proxies');
               $config->setProxyNamespace('Proxies');




Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010

                            Doctrine 2 Setup
ā€¢ Create your database connection and entity
  manager

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

             // Create EntityManager
             $em = EntityManager::create($connectionOptions, $config);




Doctrine 2        www.doctrine-project.org   www.sensiolabs.com
#sflive2010

                       Doctrine 2 Setup
ā€¢ In production you would lazily load the
  EntityManager
ā€¢ Example: $em = function()
             {
                                 static $em;
                                 if (!$em)
                                 {
                                   $em = EntityManager::create($connectionOptions, $config);
                                 }
                                 return $em;
                             }


ā€¢ In the real world I wouldnā€™t recommend that
  you use the above example
ā€¢ Symfony DI would take care of this for us

Doctrine 2   www.doctrine-project.org               www.sensiolabs.com
#sflive2010

                       Doctrine 2 Setup
ā€¢ Now you can start using your models and
  persisting entities


             $user = new User;
             $user->setName('Jonathan H. Wage');
             $em->persist($user);
             $em->flush();




Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010

                   Insert Performance
ā€¢ Inserting 20 records with Doctrine

             for ($i = 0; $i < 20; ++$i) {
                 $user = new User;
                 $user->name = 'Jonathan H. Wage';
                 $em->persist($user);
             }

             $s = microtime(true);
             $em->flush();
             $e = microtime(true);
             echo $e - $s;


Doctrine 2    www.doctrine-project.org   www.sensiolabs.com
#sflive2010

                  Insert Performance
ā€¢ Compare it to some raw PHP code


$s = microtime(true);
for ($i = 0; $i < 20; ++$i) {
    mysql_query("INSERT INTO users (name) VALUES ('Jonathan H. Wage')",
$link);
}
$e = microtime(true);
echo $e - $s;




Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010

                  Insert Performance
ā€¢ The results might be surprising to you.
  Which do you think is faster?




Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010

                  Insert Performance



             Doctrine 2                 0.0094 seconds

             mysql_query 0.0165 seconds




Doctrine 2   www.doctrine-project.org    www.sensiolabs.com
#sflive2010

                  Insert Performance
ā€¢ Doctrine 2 is faster than some raw PHP
  code? What?!?!?! HUH?
ā€¢ It does a lot less, provides no features, no
  abstraction, etc.

ā€¢ Why? The answer is transactions! Doctrine 2
  manages our transactions for us and
  efficiently executes all inserts in a single,
  short transaction. The raw PHP code
  executes 1 transaction for each insert.

Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010

                  Insert Performance
ā€¢ Here is the same raw PHP code re-visited
  with proper transaction usage.

$s = microtime(true);
mysql_query('START TRANSACTION', $link);
for ($i = 0; $i < 20; ++$i) {
    mysql_query("INSERT INTO users (name) VALUES ('Jonathan H. Wage')",
$link);
}
mysql_query('COMMIT', $link);
$e = microtime(true);
echo $e - $s;




Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010

                  Insert Performance
ā€¢ Not trying to say Doctrine 2 is faster than
  raw PHP code

ā€¢ Demonstrating that simple developer
  oversights and mis-use can cause the
  greatest performance problems




Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010

                   Insert Performance
ā€¢ This time around it only takes 0.0028
  seconds compared to the previous 0.0165
  seconds. Thatā€™s a pretty huge improvement.

ā€¢ You can read more about this on the
  Doctrine Blog

     http://www.doctrine-project.org/blog/transactions-and-performance




Doctrine 2    www.doctrine-project.org   www.sensiolabs.com
#sflive2010

             Doctrine Query Language
ā€¢ DQL parser completely re-written from
  scratch

ā€¢ ...DQL is parsed by a top down recursive
  descent parser that constructs an AST
  (abstract syntax tree).

ā€¢ ...The AST is used to generate the SQL to
  execute for your DBMS
               http://www.doctrine-project.org/documentation/manual/2_0/en/dql-doctrine-query-language


Doctrine 2    www.doctrine-project.org                       www.sensiolabs.com
#sflive2010

             Doctrine Query Language
ā€¢ Here is an example DQL query



        $q = $em->createQuery('select u from MyProjectModelUser u');
        $users = $q->execute();




Doctrine 2      www.doctrine-project.org   www.sensiolabs.com
#sflive2010

             Doctrine Query Language
ā€¢ Here is that same DQL query using the
  QueryBuilder API

             $qb = $em->createQueryBuilder()
                 ->select('u')
                 ->from('MyProjectModelUser', 'u');

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


                         http://www.doctrine-project.org/documentation/manual/2_0/en/query-builder




Doctrine 2      www.doctrine-project.org                        www.sensiolabs.com
#sflive2010

             Doctrine Query Builder
ā€¢ QueryBuilder API is the same as
  Doctrine_Query API in Doctrine 1
ā€¢ Query building and query execution are
  separated
ā€¢ True builder pattern used
ā€¢ QueryBuilder is used to build instances of
  Query
ā€¢ You donā€™t execute a QueryBuilder, you get
  the built Query instance from the
  QueryBuilder and execute it
Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010

                              Cache Drivers
ā€¢ Public interface of all cache drivers

ā€¢ fetch($id) - Fetches an entry from the
  cache.
ā€¢ contains($id) - Test if an entry exists in the
  cache.
ā€¢ save($id, $data, $lifeTime = false) - Puts
  data into the cache.
ā€¢ delete($id) - Deletes a cache entry.

Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010

                              Cache Drivers
ā€¢ Wrap existing Symfony, ZF, etc. cache driver
  instances with the Doctrine interface




Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010

                              Cache Drivers
ā€¢ deleteByRegex($regex) - Deletes cache
  entries where the key matches a regular
  expression

ā€¢ deleteByPreļ¬x($preļ¬x) - Deletes cache
  entries where the key matches a preļ¬x.

ā€¢ deleteBySuffix($suffix) - Deletes cache
  entries where the key matches a suffix.


Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010

                              Cache Drivers
ā€¢ Each driver extends the AbstractCache class
  which deļ¬nes a few abstract protected
  methods that each of the drivers must
  implement to do the actual work

ā€¢    _doFetch($id)
ā€¢    _doContains($id)
ā€¢    _doSave($id, $data, $lifeTime = false)
ā€¢    _doDelete($id)

Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010

                        APC Cache Driver
ā€¢ To use the APC cache driver you must have
  it compiled and enabled in your php.ini


             $cacheDriver = new DoctrineCommonCacheApcCache();
             $cacheDriver->save('cache_id', 'my_data');




Doctrine 2      www.doctrine-project.org   www.sensiolabs.com
#sflive2010

                Memcache Cache Driver
ā€¢ To use the memcache cache driver you
  must have it compiled and enabled in your
  php.ini

             $memcache = new Memcache();
             $memcache->connect('memcache_host', 11211);

             $cacheDriver = new DoctrineCommonCacheMemcacheCache();
             $cacheDriver->setMemcache($memcache);
             $cacheDriver->save('cache_id', 'my_data');




Doctrine 2         www.doctrine-project.org   www.sensiolabs.com
#sflive2010

                   Xcache Cache Driver
ā€¢ To use the xcache cache driver you must
  have it compiled and enabled in your
  php.ini

             $cacheDriver = new DoctrineCommonCacheXcacheCache();
             $cacheDriver->save('cache_id', 'my_data');




Doctrine 2        www.doctrine-project.org   www.sensiolabs.com
#sflive2010

                                       Result Cache
ā€¢ First you need to conļ¬gure the result cache
                $cacheDriver = new DoctrineCommonCacheApcCache();
                $config->setResultCacheImpl($cacheDriver);


ā€¢ Then you can conļ¬gure each query to use
  the result cache or not.
             $query = $em->createQuery('select u from EntitiesUser u');
             $query->useResultCache(true, 3600, 'my_query_name');


ā€¢ Executing this query the ļ¬rst time would
  populate a cache entry in $cacheDriver
  named my_query_name
Doctrine 2          www.doctrine-project.org   www.sensiolabs.com
#sflive2010

                                 Result Cache
ā€¢ Now you can clear the cache for that query
  by using the delete() method of the cache
  driver


             $cacheDriver->delete('my_query_name');




Doctrine 2    www.doctrine-project.org   www.sensiolabs.com
#sflive2010

             Command Line Interface
ā€¢ Re-written command line interface to help
  developing with Doctrine




Doctrine 2    www.doctrine-project.org   www.sensiolabs.com
#sflive2010

                                dbal:run-sql
ā€¢ Execute a manually written SQL statement
ā€¢ Execute multiple SQL statements from a ļ¬le




Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010

                        orm:clear-cache
ā€¢    Clear   all query, result and metadata cache
ā€¢    Clear   only query cache
ā€¢    Clear   only result cache
ā€¢    Clear   only metadata cache
ā€¢    Clear   a single queries result cache
ā€¢    Clear   keys that match regular expression
ā€¢    Clear   keys that match a preļ¬x
ā€¢    Clear   keys that match a suffix


Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010




             So now when you have a problem in
             Doctrine, like Symfony, you can try
             clearing the cache first :)




Doctrine 2      www.doctrine-project.org   www.sensiolabs.com
#sflive2010

             orm:convert-mapping
ā€¢ Convert metadata information between
  formats
ā€¢ Convert metadata information from an
  existing database to any supported format
  (yml, xml, annotations, etc.)
ā€¢ Convert mapping information from xml to
  yml or vice versa
ā€¢ Generate PHP classes from mapping
  information with mutators and accessors


Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010

orm:ensure-production-settings
ā€¢ Verify that Doctrine is properly conļ¬gured
  for a production environment.

ā€¢ Throws an exception when environment
  does not meet the production requirements




Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010

             orm:generate-proxies
ā€¢ Generate the proxy classes for entity
  classes.

ā€¢ 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.

Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010

                                 orm:run-dql
ā€¢ Execute a DQL query from the command
  line




Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010

                     orm:schema-tool
ā€¢ Drop, create and update your database
  schema.

ā€¢ --create option creates the initial tables for
  your schema
ā€¢ --drop option drops the the tables for your
  schema
ā€¢ --update option compares your local
  schema information to the database and
  updates it accordingly
Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010

                                    Inheritance
ā€¢ Doctrine 2 fully supports inheritance. We
  allow the following types of inheritance:

ā€¢ ...Mapped Superclasses
ā€¢ ...Single Table Inheritance
ā€¢ ...Class Table Inheritance




Doctrine 2   www.doctrine-project.org     www.sensiolabs.com
#sflive2010

             Mapped Superclasses
             /** @MappedSuperclass */
             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
             }

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

                     // ... more fields and methods
             }




Doctrine 2       www.doctrine-project.org             www.sensiolabs.com
#sflive2010

                  Mapped Superclasses


    CREATE TABLE EntitySubClass (mapped1 INTEGER NOT NULL,
    mapped2 TEXT NOT NULL,
    id INTEGER NOT NULL,
    name TEXT NOT NULL,
    related1_id INTEGER DEFAULT NULL,
    PRIMARY KEY(id))




             http://www.doctrine-project.org/documentation/manual/2_0/en/inheritance-mapping#mapped-superclasses

Doctrine 2        www.doctrine-project.org                      www.sensiolabs.com
#sflive2010

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

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




Doctrine 2        www.doctrine-project.org   www.sensiolabs.com
#sflive2010

             Single Table Inheritance
ā€¢ All entities share one table.

ā€¢ To distinguish which row represents which
  type in the hierarchy a so-called
  discriminator column is used.




             http://www.doctrine-project.org/documentation/manual/2_0/en/inheritance-mapping#single-table-inheritance


Doctrine 2         www.doctrine-project.org                        www.sensiolabs.com
#sflive2010

             Class Table Inheritance
 namespace MyProjectModel;

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

 /** @Entity */
 class Employee extends Person
 {
     // ...
 }
             http://www.doctrine-project.org/documentation/manual/2_0/en/inheritance-mapping#single-table-inheritance

Doctrine 2       www.doctrine-project.org                        www.sensiolabs.com
#sflive2010

             Class Table Inheritance
ā€¢ Each class in a hierarchy is mapped to
  several tables: its own table and the tables
  of all parent classes.
ā€¢ The table of a child class is linked to the
  table of a parent class through a foreign
  key constraint.
ā€¢ A discriminator column is used in the
  topmost table of the hierarchy because this
  is the easiest way to achieve polymorphic
  queries.

Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010

                       Batch Processing
ā€¢ Doctrine 2 offers the ability to do some
  batch processing by taking advantage of
  the transactional write-behind behavior of
  an EntityManager




Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010

                                      Bulk Inserts
ā€¢ Insert 10000 objects with a batch size of 20


             $batchSize = 20;
             for ($i = 1; $i <= 10000; ++$i) {
                 $user = new CmsUser;
                 $user->setStatus('user');
                 $user->setUsername('user' . $i);
                 $user->setName('Mr.Smith-' . $i);
                 $em->persist($user);
                 if ($i % $batchSize == 0) {
                     $em->flush();
                     $em->clear(); // Detaches all objects from Doctrine!
                 }
             }




Doctrine 2       www.doctrine-project.org    www.sensiolabs.com
#sflive2010

                                     Bulk Update
ā€¢ Bulk update with DQL



       $q = $em->createQuery('update MyProjectModelManager m set
       m.salary = m.salary * 0.9');
       $numUpdated = $q->execute();




Doctrine 2      www.doctrine-project.org   www.sensiolabs.com
#sflive2010

                                    Bulk Update
ā€¢ Bulk update by iterating over the results
  using the Query::iterate() method to avoid
  loading everything into memory at once
             $batchSize = 20;
             $i = 0;
             $q = $em->createQuery('select u from MyProjectModelUser u');
             $iterableResult = $q->iterate();
             foreach($iterableResult AS $row) {
                 $user = $row[0];
                 $user->increaseCredit();
                 $user->calculateNewBonuses();
                 if (($i % $batchSize) == 0) {
                     $em->flush(); // Executes all updates.
                     $em->clear(); // Detaches all objects from Doctrine!
                 }
                 ++$i;
             }



Doctrine 2     www.doctrine-project.org        www.sensiolabs.com
#sflive2010

                                     Bulk Delete
ā€¢ Bulk delete with DQL




       $q = $em->createQuery('delete from MyProjectModelManager m
       where m.salary > 100000');
       $numDeleted = $q->execute();




Doctrine 2     www.doctrine-project.org    www.sensiolabs.com
#sflive2010

                                        Bulk Delete
ā€¢ Just like the bulk updates you can iterate
  over a query to avoid loading everything
  into memory all at once.

             $batchSize = 20;
             $i = 0;
             $q = $em->createQuery('select u from MyProjectModelUser u');
             $iterableResult = $q->iterate();
             while (($row = $iterableResult->next()) !== false) {
                 $em->remove($row[0]);
                 if (($i % $batchSize) == 0) {
                     $em->flush(); // Executes all deletions.
                     $em->clear(); // Detaches all objects from Doctrine!
                 }
                 ++$i;
             }



Doctrine 2        www.doctrine-project.org    www.sensiolabs.com
#sflive2010

NativeQuery + ResultSetMapping
ā€¢ The NativeQuery class is used to execute
  raw SQL queries

ā€¢ The ResultSetMapping class is used to
  deļ¬ne how to hydrate the results of that
  query




Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010

NativeQuery + ResultSetMapping
ā€¢ Here is a simple example
      $rsm = new ResultSetMapping;
      $rsm->addEntityResult('DoctrineTestsModelsCMSCmsUser', 'u');
      $rsm->addFieldResult('u', 'id', 'id');
      $rsm->addFieldResult('u', 'name', 'name');

      $query = $this->_em->createNativeQuery(
          'SELECT id, name FROM cms_users WHERE username = ?',
          $rsm
      );
      $query->setParameter(1, 'romanb');

      $users = $query->getResult();




Doctrine 2     www.doctrine-project.org   www.sensiolabs.com
#sflive2010

NativeQuery + ResultSetMapping
ā€¢ The result of $users would look like


             array(
                 [0] => User (Object)
             )




Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010

NativeQuery + ResultSetMapping
ā€¢ This means you will always be able to
  fallback to the power of raw SQL without
  losing the ability to hydrate the data to your
  entities




Doctrine 2   www.doctrine-project.org   www.sensiolabs.com
#sflive2010



              Questions?
     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


Doctrine 2     www.doctrine-project.org   www.sensiolabs.com

More Related Content

What's hot

Android Malware 2020 (CCCS-CIC-AndMal-2020)
Android Malware 2020 (CCCS-CIC-AndMal-2020)Android Malware 2020 (CCCS-CIC-AndMal-2020)
Android Malware 2020 (CCCS-CIC-AndMal-2020)Indraneel Dabhade
Ā 
Original slides from Ryan Dahl's NodeJs intro talk
Original slides from Ryan Dahl's NodeJs intro talkOriginal slides from Ryan Dahl's NodeJs intro talk
Original slides from Ryan Dahl's NodeJs intro talkAarti Parikh
Ā 
Astar algorithm
Astar algorithmAstar algorithm
Astar algorithmShuqing Zhang
Ā 
Python: Migrating from Procedural to Object-Oriented Programming
Python: Migrating from Procedural to Object-Oriented ProgrammingPython: Migrating from Procedural to Object-Oriented Programming
Python: Migrating from Procedural to Object-Oriented ProgrammingDamian T. Gordon
Ā 
State Space Representation and Search
State Space Representation and SearchState Space Representation and Search
State Space Representation and SearchHitesh Mohapatra
Ā 
Control structures functions and modules in python programming
Control structures functions and modules in python programmingControl structures functions and modules in python programming
Control structures functions and modules in python programmingSrinivas Narasegouda
Ā 
Conditions In C# C-Sharp
Conditions In C# C-SharpConditions In C# C-Sharp
Conditions In C# C-SharpAbid Kohistani
Ā 
Unification and Lifting
Unification and LiftingUnification and Lifting
Unification and LiftingMegha Sharma
Ā 
Using BigDecimal and double
Using BigDecimal and doubleUsing BigDecimal and double
Using BigDecimal and doublePeter Lawrey
Ā 
Guessing Game (1).pptx
Guessing Game (1).pptxGuessing Game (1).pptx
Guessing Game (1).pptxTYEXTCB04RajPatil
Ā 
Big Data Analytics with Spark
Big Data Analytics with SparkBig Data Analytics with Spark
Big Data Analytics with SparkMohammed Guller
Ā 
Syntax and semantics of propositional logic
Syntax and semantics of propositional logicSyntax and semantics of propositional logic
Syntax and semantics of propositional logicJanet Stemwedel
Ā 
Š›ŠµŠŗцŠøя ā„–11 "ŠžŃŠ½Š¾Š²Ń‹ Š½ŠµŠ¹Ń€Š¾Š½Š½Ń‹Ń… сŠµŃ‚ŠµŠ¹"
Š›ŠµŠŗцŠøя ā„–11 "ŠžŃŠ½Š¾Š²Ń‹ Š½ŠµŠ¹Ń€Š¾Š½Š½Ń‹Ń… сŠµŃ‚ŠµŠ¹" Š›ŠµŠŗцŠøя ā„–11 "ŠžŃŠ½Š¾Š²Ń‹ Š½ŠµŠ¹Ń€Š¾Š½Š½Ń‹Ń… сŠµŃ‚ŠµŠ¹"
Š›ŠµŠŗцŠøя ā„–11 "ŠžŃŠ½Š¾Š²Ń‹ Š½ŠµŠ¹Ń€Š¾Š½Š½Ń‹Ń… сŠµŃ‚ŠµŠ¹" Technosphere1
Ā 
5.-Knowledge-Representation-in-AI_010824.pdf
5.-Knowledge-Representation-in-AI_010824.pdf5.-Knowledge-Representation-in-AI_010824.pdf
5.-Knowledge-Representation-in-AI_010824.pdfSakshiSingh770619
Ā 

What's hot (20)

Scheduling in cloud
Scheduling in cloudScheduling in cloud
Scheduling in cloud
Ā 
Android Malware 2020 (CCCS-CIC-AndMal-2020)
Android Malware 2020 (CCCS-CIC-AndMal-2020)Android Malware 2020 (CCCS-CIC-AndMal-2020)
Android Malware 2020 (CCCS-CIC-AndMal-2020)
Ā 
Original slides from Ryan Dahl's NodeJs intro talk
Original slides from Ryan Dahl's NodeJs intro talkOriginal slides from Ryan Dahl's NodeJs intro talk
Original slides from Ryan Dahl's NodeJs intro talk
Ā 
Astar algorithm
Astar algorithmAstar algorithm
Astar algorithm
Ā 
Chapter 4 (final)
Chapter 4 (final)Chapter 4 (final)
Chapter 4 (final)
Ā 
Python: Migrating from Procedural to Object-Oriented Programming
Python: Migrating from Procedural to Object-Oriented ProgrammingPython: Migrating from Procedural to Object-Oriented Programming
Python: Migrating from Procedural to Object-Oriented Programming
Ā 
State Space Representation and Search
State Space Representation and SearchState Space Representation and Search
State Space Representation and Search
Ā 
Control structures functions and modules in python programming
Control structures functions and modules in python programmingControl structures functions and modules in python programming
Control structures functions and modules in python programming
Ā 
Conditions In C# C-Sharp
Conditions In C# C-SharpConditions In C# C-Sharp
Conditions In C# C-Sharp
Ā 
Unification and Lifting
Unification and LiftingUnification and Lifting
Unification and Lifting
Ā 
Using BigDecimal and double
Using BigDecimal and doubleUsing BigDecimal and double
Using BigDecimal and double
Ā 
Guessing Game (1).pptx
Guessing Game (1).pptxGuessing Game (1).pptx
Guessing Game (1).pptx
Ā 
Big Data Analytics with Spark
Big Data Analytics with SparkBig Data Analytics with Spark
Big Data Analytics with Spark
Ā 
Hazelcast Introduction
Hazelcast IntroductionHazelcast Introduction
Hazelcast Introduction
Ā 
Reinforcement Learning
Reinforcement LearningReinforcement Learning
Reinforcement Learning
Ā 
Forward Backward Chaining
Forward Backward ChainingForward Backward Chaining
Forward Backward Chaining
Ā 
Syntax and semantics of propositional logic
Syntax and semantics of propositional logicSyntax and semantics of propositional logic
Syntax and semantics of propositional logic
Ā 
AI_6 Uncertainty
AI_6 Uncertainty AI_6 Uncertainty
AI_6 Uncertainty
Ā 
Š›ŠµŠŗцŠøя ā„–11 "ŠžŃŠ½Š¾Š²Ń‹ Š½ŠµŠ¹Ń€Š¾Š½Š½Ń‹Ń… сŠµŃ‚ŠµŠ¹"
Š›ŠµŠŗцŠøя ā„–11 "ŠžŃŠ½Š¾Š²Ń‹ Š½ŠµŠ¹Ń€Š¾Š½Š½Ń‹Ń… сŠµŃ‚ŠµŠ¹" Š›ŠµŠŗцŠøя ā„–11 "ŠžŃŠ½Š¾Š²Ń‹ Š½ŠµŠ¹Ń€Š¾Š½Š½Ń‹Ń… сŠµŃ‚ŠµŠ¹"
Š›ŠµŠŗцŠøя ā„–11 "ŠžŃŠ½Š¾Š²Ń‹ Š½ŠµŠ¹Ń€Š¾Š½Š½Ń‹Ń… сŠµŃ‚ŠµŠ¹"
Ā 
5.-Knowledge-Representation-in-AI_010824.pdf
5.-Knowledge-Representation-in-AI_010824.pdf5.-Knowledge-Representation-in-AI_010824.pdf
5.-Knowledge-Representation-in-AI_010824.pdf
Ā 

Viewers also liked

What Is Doctrine?
What Is Doctrine?What Is Doctrine?
What Is Doctrine?Jonathan Wage
Ā 
Effective Doctrine2: Performance Tips for Symfony2 Developers
Effective Doctrine2: Performance Tips for Symfony2 DevelopersEffective Doctrine2: Performance Tips for Symfony2 Developers
Effective Doctrine2: Performance Tips for Symfony2 DevelopersMarcin Chwedziak
Ā 
Object Relational Mapping in PHP
Object Relational Mapping in PHPObject Relational Mapping in PHP
Object Relational Mapping in PHPRob Knight
Ā 
Symfony tips and tricks
Symfony tips and tricksSymfony tips and tricks
Symfony tips and tricksJavier Eguiluz
Ā 
New Symfony Tips & Tricks (SymfonyCon Paris 2015)
New Symfony Tips & Tricks (SymfonyCon Paris 2015)New Symfony Tips & Tricks (SymfonyCon Paris 2015)
New Symfony Tips & Tricks (SymfonyCon Paris 2015)Javier Eguiluz
Ā 
DDD with Behat
DDD with BehatDDD with Behat
DDD with BehatAnton Serdyuk
Ā 
TRADE AND ECONOMIC DEVELOPMENT
TRADE AND ECONOMIC DEVELOPMENTTRADE AND ECONOMIC DEVELOPMENT
TRADE AND ECONOMIC DEVELOPMENTClƔudio Carneiro
Ā 
Understanding Doctrine at True North PHP 2013
Understanding Doctrine at True North PHP 2013Understanding Doctrine at True North PHP 2013
Understanding Doctrine at True North PHP 2013Juti Noppornpitak
Ā 
Symfony 2.0 on PHP 5.3
Symfony 2.0 on PHP 5.3Symfony 2.0 on PHP 5.3
Symfony 2.0 on PHP 5.3Fabien Potencier
Ā 
Les rĆØgles de passage
Les rĆØgles de passageLes rĆØgles de passage
Les rĆØgles de passagemarwa baich
Ā 
Symfony2. Database and Doctrine
Symfony2. Database and DoctrineSymfony2. Database and Doctrine
Symfony2. Database and DoctrineVladimir Doroshenko
Ā 
HĘ°į»›ng dįŗ«n lįŗ­p trƬnh web vį»›i PHP - NgĆ y 2
HĘ°į»›ng dįŗ«n lįŗ­p trƬnh web vį»›i PHP - NgĆ y 2HĘ°į»›ng dįŗ«n lįŗ­p trƬnh web vį»›i PHP - NgĆ y 2
HĘ°į»›ng dįŗ«n lįŗ­p trƬnh web vį»›i PHP - NgĆ y 2Nguyį»…n Tuįŗ„n Quį»³nh
Ā 
Symfony2 and Doctrine2 Integration
Symfony2 and Doctrine2 IntegrationSymfony2 and Doctrine2 Integration
Symfony2 and Doctrine2 IntegrationJonathan Wage
Ā 
Ssm Theology Week 8
Ssm Theology Week 8Ssm Theology Week 8
Ssm Theology Week 8Alan Shelby
Ā 
Ecclesiology Part 4 - Discipleship 2 -The Cost of discipleship
Ecclesiology Part 4  -  Discipleship 2 -The Cost of discipleshipEcclesiology Part 4  -  Discipleship 2 -The Cost of discipleship
Ecclesiology Part 4 - Discipleship 2 -The Cost of discipleshipRobert Tan
Ā 
Ssm Theology Week 2
Ssm Theology Week 2Ssm Theology Week 2
Ssm Theology Week 2Alan Shelby
Ā 
Is The Trinity Doctrine Divinely Inspired
Is The Trinity Doctrine Divinely InspiredIs The Trinity Doctrine Divinely Inspired
Is The Trinity Doctrine Divinely Inspiredzakir2012
Ā 
Ecclesiology Part 2 - The Purpose of the Church.
Ecclesiology Part 2 - The Purpose of the Church.Ecclesiology Part 2 - The Purpose of the Church.
Ecclesiology Part 2 - The Purpose of the Church.Robert Tan
Ā 

Viewers also liked (20)

What Is Doctrine?
What Is Doctrine?What Is Doctrine?
What Is Doctrine?
Ā 
Effective Doctrine2: Performance Tips for Symfony2 Developers
Effective Doctrine2: Performance Tips for Symfony2 DevelopersEffective Doctrine2: Performance Tips for Symfony2 Developers
Effective Doctrine2: Performance Tips for Symfony2 Developers
Ā 
Object Relational Mapping in PHP
Object Relational Mapping in PHPObject Relational Mapping in PHP
Object Relational Mapping in PHP
Ā 
Symfony tips and tricks
Symfony tips and tricksSymfony tips and tricks
Symfony tips and tricks
Ā 
New Symfony Tips & Tricks (SymfonyCon Paris 2015)
New Symfony Tips & Tricks (SymfonyCon Paris 2015)New Symfony Tips & Tricks (SymfonyCon Paris 2015)
New Symfony Tips & Tricks (SymfonyCon Paris 2015)
Ā 
hbase lab
hbase labhbase lab
hbase lab
Ā 
DDD with Behat
DDD with BehatDDD with Behat
DDD with Behat
Ā 
TRADE AND ECONOMIC DEVELOPMENT
TRADE AND ECONOMIC DEVELOPMENTTRADE AND ECONOMIC DEVELOPMENT
TRADE AND ECONOMIC DEVELOPMENT
Ā 
Understanding Doctrine at True North PHP 2013
Understanding Doctrine at True North PHP 2013Understanding Doctrine at True North PHP 2013
Understanding Doctrine at True North PHP 2013
Ā 
Symfony 2.0 on PHP 5.3
Symfony 2.0 on PHP 5.3Symfony 2.0 on PHP 5.3
Symfony 2.0 on PHP 5.3
Ā 
Les rĆØgles de passage
Les rĆØgles de passageLes rĆØgles de passage
Les rĆØgles de passage
Ā 
Symfony2. Database and Doctrine
Symfony2. Database and DoctrineSymfony2. Database and Doctrine
Symfony2. Database and Doctrine
Ā 
HĘ°į»›ng dįŗ«n lįŗ­p trƬnh web vį»›i PHP - NgĆ y 2
HĘ°į»›ng dįŗ«n lįŗ­p trƬnh web vį»›i PHP - NgĆ y 2HĘ°į»›ng dįŗ«n lįŗ­p trƬnh web vį»›i PHP - NgĆ y 2
HĘ°į»›ng dįŗ«n lįŗ­p trƬnh web vį»›i PHP - NgĆ y 2
Ā 
Symfony2 and Doctrine2 Integration
Symfony2 and Doctrine2 IntegrationSymfony2 and Doctrine2 Integration
Symfony2 and Doctrine2 Integration
Ā 
Ssm Theology Week 8
Ssm Theology Week 8Ssm Theology Week 8
Ssm Theology Week 8
Ā 
Ecclesiology Part 4 - Discipleship 2 -The Cost of discipleship
Ecclesiology Part 4  -  Discipleship 2 -The Cost of discipleshipEcclesiology Part 4  -  Discipleship 2 -The Cost of discipleship
Ecclesiology Part 4 - Discipleship 2 -The Cost of discipleship
Ā 
Ssm Theology Week 2
Ssm Theology Week 2Ssm Theology Week 2
Ssm Theology Week 2
Ā 
Ecclessiology 2
Ecclessiology 2Ecclessiology 2
Ecclessiology 2
Ā 
Is The Trinity Doctrine Divinely Inspired
Is The Trinity Doctrine Divinely InspiredIs The Trinity Doctrine Divinely Inspired
Is The Trinity Doctrine Divinely Inspired
Ā 
Ecclesiology Part 2 - The Purpose of the Church.
Ecclesiology Part 2 - The Purpose of the Church.Ecclesiology Part 2 - The Purpose of the Church.
Ecclesiology Part 2 - The Purpose of the Church.
Ā 

Similar to Doctrine 2 - Not The Same Old Php Orm

Doctrine2 enterpice
Doctrine2 enterpiceDoctrine2 enterpice
Doctrine2 enterpiceescorpion2610
Ā 
Doctrine 2 - Enterprise Persistence Layer For PHP
Doctrine 2 - Enterprise Persistence Layer For PHPDoctrine 2 - Enterprise Persistence Layer For PHP
Doctrine 2 - Enterprise Persistence Layer For PHPJonathan Wage
Ā 
Introduction To Doctrine 2
Introduction To Doctrine 2Introduction To Doctrine 2
Introduction To Doctrine 2Jonathan Wage
Ā 
Intro to Python for C# Developers
Intro to Python for C# DevelopersIntro to Python for C# Developers
Intro to Python for C# DevelopersSarah Dutkiewicz
Ā 
What's New In Doctrine
What's New In DoctrineWhat's New In Doctrine
What's New In DoctrineJonathan Wage
Ā 
Introduction to the intermediate Python - v1.1
Introduction to the intermediate Python - v1.1Introduction to the intermediate Python - v1.1
Introduction to the intermediate Python - v1.1Andrei KUCHARAVY
Ā 
Doctrine 2: Enterprise Persistence Layer for PHP
Doctrine 2: Enterprise Persistence Layer for PHPDoctrine 2: Enterprise Persistence Layer for PHP
Doctrine 2: Enterprise Persistence Layer for PHPJonathan Wage
Ā 
Tyrion Cannister Neural Styles by Dora Korpar and Siphan Bou
Tyrion Cannister Neural Styles by Dora Korpar and Siphan BouTyrion Cannister Neural Styles by Dora Korpar and Siphan Bou
Tyrion Cannister Neural Styles by Dora Korpar and Siphan BouDocker, Inc.
Ā 
Overcoming common knowledge: 100k nodes in a single folder
Overcoming common knowledge: 100k nodes in a single folderOvercoming common knowledge: 100k nodes in a single folder
Overcoming common knowledge: 100k nodes in a single folderITD Systems
Ā 
How to not suck at JavaScript
How to not suck at JavaScriptHow to not suck at JavaScript
How to not suck at JavaScripttmont
Ā 
Refactor your code: when, why and how?
Refactor your code: when, why and how?Refactor your code: when, why and how?
Refactor your code: when, why and how?Nacho Cougil
Ā 
Ā« Training Within Software Ā» using Dojo and Mob Programming by Bernard Notari...
Ā« Training Within Software Ā» using Dojo and Mob Programming by Bernard Notari...Ā« Training Within Software Ā» using Dojo and Mob Programming by Bernard Notari...
Ā« Training Within Software Ā» using Dojo and Mob Programming by Bernard Notari...Institut Lean France
Ā 
Libertyvasion2010
Libertyvasion2010Libertyvasion2010
Libertyvasion2010Jonathan Wage
Ā 
When Drupal meets OpenData
When Drupal meets OpenDataWhen Drupal meets OpenData
When Drupal meets OpenDataTwinbit
Ā 
Ruby codebases in an entropic universe
Ruby codebases in an entropic universeRuby codebases in an entropic universe
Ruby codebases in an entropic universeNiranjan Paranjape
Ā 
Java for XPages Development
Java for XPages DevelopmentJava for XPages Development
Java for XPages DevelopmentTeamstudio
Ā 

Similar to Doctrine 2 - Not The Same Old Php Orm (20)

Doctrine2
Doctrine2Doctrine2
Doctrine2
Ā 
Doctrine2 enterpice
Doctrine2 enterpiceDoctrine2 enterpice
Doctrine2 enterpice
Ā 
Doctrine 2 - Enterprise Persistence Layer For PHP
Doctrine 2 - Enterprise Persistence Layer For PHPDoctrine 2 - Enterprise Persistence Layer For PHP
Doctrine 2 - Enterprise Persistence Layer For PHP
Ā 
Introduction To Doctrine 2
Introduction To Doctrine 2Introduction To Doctrine 2
Introduction To Doctrine 2
Ā 
Intro to Python for C# Developers
Intro to Python for C# DevelopersIntro to Python for C# Developers
Intro to Python for C# Developers
Ā 
What's New In Doctrine
What's New In DoctrineWhat's New In Doctrine
What's New In Doctrine
Ā 
Introduction to the intermediate Python - v1.1
Introduction to the intermediate Python - v1.1Introduction to the intermediate Python - v1.1
Introduction to the intermediate Python - v1.1
Ā 
Doctrine 2: Enterprise Persistence Layer for PHP
Doctrine 2: Enterprise Persistence Layer for PHPDoctrine 2: Enterprise Persistence Layer for PHP
Doctrine 2: Enterprise Persistence Layer for PHP
Ā 
Tyrion Cannister Neural Styles by Dora Korpar and Siphan Bou
Tyrion Cannister Neural Styles by Dora Korpar and Siphan BouTyrion Cannister Neural Styles by Dora Korpar and Siphan Bou
Tyrion Cannister Neural Styles by Dora Korpar and Siphan Bou
Ā 
Overcoming common knowledge: 100k nodes in a single folder
Overcoming common knowledge: 100k nodes in a single folderOvercoming common knowledge: 100k nodes in a single folder
Overcoming common knowledge: 100k nodes in a single folder
Ā 
Introduction to Python
Introduction to PythonIntroduction to Python
Introduction to Python
Ā 
How to not suck at JavaScript
How to not suck at JavaScriptHow to not suck at JavaScript
How to not suck at JavaScript
Ā 
Refactor your code: when, why and how?
Refactor your code: when, why and how?Refactor your code: when, why and how?
Refactor your code: when, why and how?
Ā 
Introduction to python
Introduction to pythonIntroduction to python
Introduction to python
Ā 
Js tips & tricks
Js tips & tricksJs tips & tricks
Js tips & tricks
Ā 
Ā« Training Within Software Ā» using Dojo and Mob Programming by Bernard Notari...
Ā« Training Within Software Ā» using Dojo and Mob Programming by Bernard Notari...Ā« Training Within Software Ā» using Dojo and Mob Programming by Bernard Notari...
Ā« Training Within Software Ā» using Dojo and Mob Programming by Bernard Notari...
Ā 
Libertyvasion2010
Libertyvasion2010Libertyvasion2010
Libertyvasion2010
Ā 
When Drupal meets OpenData
When Drupal meets OpenDataWhen Drupal meets OpenData
When Drupal meets OpenData
Ā 
Ruby codebases in an entropic universe
Ruby codebases in an entropic universeRuby codebases in an entropic universe
Ruby codebases in an entropic universe
Ā 
Java for XPages Development
Java for XPages DevelopmentJava for XPages Development
Java for XPages Development
Ā 

More from Jonathan Wage

Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For BeginnersJonathan Wage
Ā 
OpenSky Infrastructure
OpenSky InfrastructureOpenSky Infrastructure
OpenSky InfrastructureJonathan Wage
Ā 
Doctrine In The Real World sflive2011 Paris
Doctrine In The Real World sflive2011 ParisDoctrine In The Real World sflive2011 Paris
Doctrine In The Real World sflive2011 ParisJonathan Wage
Ā 
Symfony2 from the Trenches
Symfony2 from the TrenchesSymfony2 from the Trenches
Symfony2 from the TrenchesJonathan Wage
Ā 
Doctrine in the Real World
Doctrine in the Real WorldDoctrine in the Real World
Doctrine in the Real WorldJonathan Wage
Ā 
ZendCon2010 Doctrine MongoDB ODM
ZendCon2010 Doctrine MongoDB ODMZendCon2010 Doctrine MongoDB ODM
ZendCon2010 Doctrine MongoDB ODMJonathan Wage
Ā 
ZendCon2010 The Doctrine Project
ZendCon2010 The Doctrine ProjectZendCon2010 The Doctrine Project
ZendCon2010 The Doctrine ProjectJonathan Wage
Ā 
Symfony Day 2010 Doctrine MongoDB ODM
Symfony Day 2010 Doctrine MongoDB ODMSymfony Day 2010 Doctrine MongoDB ODM
Symfony Day 2010 Doctrine MongoDB ODMJonathan Wage
Ā 
Doctrine MongoDB Object Document Mapper
Doctrine MongoDB Object Document MapperDoctrine MongoDB Object Document Mapper
Doctrine MongoDB Object Document MapperJonathan Wage
Ā 
Sympal A Cmf Based On Symfony
Sympal   A Cmf Based On SymfonySympal   A Cmf Based On Symfony
Sympal A Cmf Based On SymfonyJonathan Wage
Ā 
Symfony 1.3 + Doctrine 1.2
Symfony 1.3 + Doctrine 1.2Symfony 1.3 + Doctrine 1.2
Symfony 1.3 + Doctrine 1.2Jonathan Wage
Ā 
Sympal - The flexible Symfony CMS
Sympal - The flexible Symfony CMSSympal - The flexible Symfony CMS
Sympal - The flexible Symfony CMSJonathan Wage
Ā 
What's new in Doctrine
What's new in DoctrineWhat's new in Doctrine
What's new in DoctrineJonathan Wage
Ā 
Sympal - Symfony CMS Preview
Sympal - Symfony CMS PreviewSympal - Symfony CMS Preview
Sympal - Symfony CMS PreviewJonathan Wage
Ā 
Doctrine Php Object Relational Mapper
Doctrine Php Object Relational MapperDoctrine Php Object Relational Mapper
Doctrine Php Object Relational MapperJonathan Wage
Ā 
Sympal - The Flexible Symfony Cms
Sympal - The Flexible Symfony CmsSympal - The Flexible Symfony Cms
Sympal - The Flexible Symfony CmsJonathan Wage
Ā 

More from Jonathan Wage (16)

Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For Beginners
Ā 
OpenSky Infrastructure
OpenSky InfrastructureOpenSky Infrastructure
OpenSky Infrastructure
Ā 
Doctrine In The Real World sflive2011 Paris
Doctrine In The Real World sflive2011 ParisDoctrine In The Real World sflive2011 Paris
Doctrine In The Real World sflive2011 Paris
Ā 
Symfony2 from the Trenches
Symfony2 from the TrenchesSymfony2 from the Trenches
Symfony2 from the Trenches
Ā 
Doctrine in the Real World
Doctrine in the Real WorldDoctrine in the Real World
Doctrine in the Real World
Ā 
ZendCon2010 Doctrine MongoDB ODM
ZendCon2010 Doctrine MongoDB ODMZendCon2010 Doctrine MongoDB ODM
ZendCon2010 Doctrine MongoDB ODM
Ā 
ZendCon2010 The Doctrine Project
ZendCon2010 The Doctrine ProjectZendCon2010 The Doctrine Project
ZendCon2010 The Doctrine Project
Ā 
Symfony Day 2010 Doctrine MongoDB ODM
Symfony Day 2010 Doctrine MongoDB ODMSymfony Day 2010 Doctrine MongoDB ODM
Symfony Day 2010 Doctrine MongoDB ODM
Ā 
Doctrine MongoDB Object Document Mapper
Doctrine MongoDB Object Document MapperDoctrine MongoDB Object Document Mapper
Doctrine MongoDB Object Document Mapper
Ā 
Sympal A Cmf Based On Symfony
Sympal   A Cmf Based On SymfonySympal   A Cmf Based On Symfony
Sympal A Cmf Based On Symfony
Ā 
Symfony 1.3 + Doctrine 1.2
Symfony 1.3 + Doctrine 1.2Symfony 1.3 + Doctrine 1.2
Symfony 1.3 + Doctrine 1.2
Ā 
Sympal - The flexible Symfony CMS
Sympal - The flexible Symfony CMSSympal - The flexible Symfony CMS
Sympal - The flexible Symfony CMS
Ā 
What's new in Doctrine
What's new in DoctrineWhat's new in Doctrine
What's new in Doctrine
Ā 
Sympal - Symfony CMS Preview
Sympal - Symfony CMS PreviewSympal - Symfony CMS Preview
Sympal - Symfony CMS Preview
Ā 
Doctrine Php Object Relational Mapper
Doctrine Php Object Relational MapperDoctrine Php Object Relational Mapper
Doctrine Php Object Relational Mapper
Ā 
Sympal - The Flexible Symfony Cms
Sympal - The Flexible Symfony CmsSympal - The Flexible Symfony Cms
Sympal - The Flexible Symfony Cms
Ā 

Recently uploaded

Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
Ā 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
Ā 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
Ā 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
Ā 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
Ā 
šŸ¬ The future of MySQL is Postgres šŸ˜
šŸ¬  The future of MySQL is Postgres   šŸ˜šŸ¬  The future of MySQL is Postgres   šŸ˜
šŸ¬ The future of MySQL is Postgres šŸ˜RTylerCroy
Ā 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
Ā 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
Ā 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
Ā 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEarley Information Science
Ā 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
Ā 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service šŸø 8923113531 šŸŽ° Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service šŸø 8923113531 šŸŽ° Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service šŸø 8923113531 šŸŽ° Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service šŸø 8923113531 šŸŽ° Avail...gurkirankumar98700
Ā 
Finology Group ā€“ Insurtech Innovation Award 2024
Finology Group ā€“ Insurtech Innovation Award 2024Finology Group ā€“ Insurtech Innovation Award 2024
Finology Group ā€“ Insurtech Innovation Award 2024The Digital Insurer
Ā 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilV3cube
Ā 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024The Digital Insurer
Ā 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
Ā 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsRoshan Dwivedi
Ā 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
Ā 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
Ā 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
Ā 

Recently uploaded (20)

Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
Ā 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
Ā 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
Ā 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Ā 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
Ā 
šŸ¬ The future of MySQL is Postgres šŸ˜
šŸ¬  The future of MySQL is Postgres   šŸ˜šŸ¬  The future of MySQL is Postgres   šŸ˜
šŸ¬ The future of MySQL is Postgres šŸ˜
Ā 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
Ā 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
Ā 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
Ā 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
Ā 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
Ā 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service šŸø 8923113531 šŸŽ° Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service šŸø 8923113531 šŸŽ° Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service šŸø 8923113531 šŸŽ° Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service šŸø 8923113531 šŸŽ° Avail...
Ā 
Finology Group ā€“ Insurtech Innovation Award 2024
Finology Group ā€“ Insurtech Innovation Award 2024Finology Group ā€“ Insurtech Innovation Award 2024
Finology Group ā€“ Insurtech Innovation Award 2024
Ā 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of Brazil
Ā 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Ā 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
Ā 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Ā 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
Ā 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
Ā 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
Ā 

Doctrine 2 - Not The Same Old Php Orm

  • 1. #sflive2010 Doctrine 2 Not the same Old PHP ORM Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 2. #sflive2010 What is different in Doctrine 2? Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 3. #sflive2010 New code, new concepts, different workļ¬‚ow Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 4. #sflive2010 100% re-written codebase for PHP 5.3 Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 5. #sflive2010 Are you scared? Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 6. #sflive2010 You shouldnā€™t be! It is a very exciting thing for PHP and change is a good thing! Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 7. #sflive2010 We learned lots building Doctrine 1 and we used that to help us build Doctrine 2 Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 8. #sflive2010 Let me tell you why! Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 9. #sflive2010 Performance of Doctrine 1 To hydrate 5000 records in Doctrine 1 it takes roughly 4.3 seconds. Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 10. #sflive2010 Performance of Doctrine 2 Under Doctrine 2, hydrating those same 5000 records only takes 1.4 seconds. Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 11. #sflive2010 Performance of Doctrine 2 ...and with 10000 records it still only takes about 3.5 seconds. Twice the data and still faster than Doctrine 1 Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 12. #sflive2010 Performance of Doctrine 2 ā€¢ More interesting than the numbers themselves is the percentage improvement over Doctrine 1 Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 13. #sflive2010 Why is it faster? ā€¢ PHP 5.3 gives us a huge performance improvement when using a heavily OO framework like Doctrine ā€¢ Better optimized hydration algorithm ā€¢ New query and result caching implementations ā€¢ All around more explicit and less magical code results in better and faster code. ā€¢ Killed the magical aspect of Doctrine 1 Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 14. #sflive2010 Why kill the magic? ā€¢ Eliminate the WTF? factor of Doctrine 1 Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 15. #sflive2010 The Doctrine 1 magical features are both a blessing and a curse Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 16. #sflive2010 Blessing and a Curse ā€¢ Magic is great when it works ā€¢ The magic you love is also the cause of all the pain youā€™ve felt with Doctrine 1 ā€¢ When it doesnā€™t work it is hard to debug ā€¢ Edge cases are hard to ļ¬x ā€¢ Edge cases are hard to work around ā€¢ Edge cases, edge cases, edge cases ā€¢ Everything is okay until you try and go outside the box the magic provides ā€¢ ...magic is slow Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 17. #sflive2010 How will we replace the magic? This new thing called OOP :) ā€¢ Object Composition ā€¢ Inheritance ā€¢ Aggregation ā€¢ Containment ā€¢ Encapsulation ā€¢ ...etc Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 18. #sflive2010 Will Doctrine 2 have behaviors? Yes and No Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 19. #sflive2010 The No ā€¢ We wonā€™t have any concept of ā€œmodel behaviorsā€ ā€¢ Behaviors were a made up concept for Doctrine 1 to work with its extremely intrusive architecture. ā€¢ It tries to do things that PHP does not allow and is the result of lots of problems in Doctrine 1 Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 20. #sflive2010 The Yes ā€¢ Everything you can do in Doctrine 1 you can do in Doctrine 2, just in a different way. ā€¢ ā€œBehaviorā€ like functionality will be bundled as extensions for Doctrine 2 and will just contain normal OO PHP code that wraps/ extends Doctrine code or is meant to be wrapped or extended by your entities. Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 21. #sflive2010 What did we use to build Doctrine 2? Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 22. #sflive2010 Doctrine 2 Tool Belt ā€¢ phpUnit 3.4.10 - Unit Testing ā€¢ Phing - Packaging and Distribution ā€¢ Symfony YAML Component ā€¢ Sismo - Continuous Integration ā€¢ Subversion - Source Control ā€¢ Jira - Issue Tracking and Management ā€¢ Trac - Subversion Timeline, Source Code Browser, Changeset Viewer Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 23. #sflive2010 Doctrine 2 Architecture ā€¢ Entities ā€¢ Lightweight persistent domain object ā€¢ Regular PHP class ā€¢ Does not extend any base Doctrine class ā€¢ Cannot be ļ¬nal or contain ļ¬nal methods ā€¢ Any two entities in a hierarchy of classes must not have a mapped property with the same name ā€¢ Supports inheritance, polymorphic associations and polymorphic queries. ā€¢ Both abstract and concrete classes can be entities ā€¢ Entities may extend non-entity classes as well as entity classes, and non-entity classes may extend entity classes Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 24. #sflive2010 Doctrine 2 Architecture ā€¢ Your entities in Doctrine 2 donā€™t require that you extend a base class like in Doctrine 1! No more imposing on your domain model! namespace Entities; class User { private $id; private $name; private $address; } Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 25. #sflive2010 Doctrine 2 Architecture ā€¢ The EntityManager ā€¢ Central access point to the ORM functionality provided by Doctrine 2. API is used to manage the persistence of your objects and to query for persistent objects. ā€¢ Employes transactional write behind strategy that delays the execution of SQL statements in order to execute them in the most efficient way ā€¢ Execute at end of transaction so that all write locks are quickly releases ā€¢ Internally an EntityManager uses a UnitOfWork to keep track of your objects Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 26. #sflive2010 Unit Testing ā€¢ Tests are ran against multiple DBMS types. This is something that was not possible with the Doctrine 1 test suite. ā€¢ ...Sqlite ā€¢ ...MySQL ā€¢ ...Oracle ā€¢ ...PgSQL ā€¢ ...more to come Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 27. #sflive2010 Unit Testing ā€¢ 859 Test Cases ā€¢ 2152 Assertions ā€¢ Tests run in a few seconds compared to 30-40 seconds for Doctrine 1 ā€¢ Much more granular and explicit unit tests ā€¢ Easier to debug failed tests ā€¢ Continuously integrated by Sismo :) Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 28. #sflive2010 Sismo ā€“ No, Sismo is not available yet!!!!!!!!! :) ā€“ Want it? Bug Fabien! Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 29. #sflive2010 Database Abstraction Layer ā€¢ Separate standalone package and namespace (DoctrineDBAL). ā€¢ Can be used standalone. ā€¢ Much improved over Doctrine 1 in regards to the API for database introspection and schema management. Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 30. #sflive2010 Database Abstraction Layer ā€¢ Hopefully Doctrine 2 DBAL can be the defacto standard DBAL for PHP 5.3 in the future like MDB and MDB2 were in PEAR ā€¢ Maybe we can make this happen for PEAR2? Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 31. #sflive2010 DBAL Data API ā€¢ prepare($sql) - Prepare a given sql statement and return the DoctrineDBAL DriverStatement instance. ā€¢ executeUpdate($sql, array $params) - Executes a prepared statement with the given sql and parameters and returns the affected rows count. ā€¢ execute($sql, array $params) - Creates a prepared statement for the given sql and passes the parameters to the execute method, then returning the statement. ā€¢ fetchAll($sql, array $params) - Execute the query and fetch all results into an array. ā€¢ fetchArray($sql, array $params) - Numeric index retrieval of ļ¬rst result row of the given query. ā€¢ fetchBoth($sql, array $params) - Both numeric and assoc column name retrieval of the ļ¬rst result row. ā€¢ fetchColumn($sql, array $params, $colnum) - Retrieve only the given column of the ļ¬rst result row. ā€¢ fetchRow($sql, array $params) - Retrieve assoc row of the ļ¬rst result row. ā€¢ select($sql, $limit, $offset) - Modify the given query with a limit clause. ā€¢ delete($tableName, array $identiļ¬er) - Delete all rows of a table matching the given identiļ¬er, where keys are column names. ā€¢ insert($tableName, array $data) - Insert a row into the given table name using the Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 32. #sflive2010 DBAL Introspection API ā€¢ listDatabases() ā€¢ listFunctions() ā€¢ listSequences() ā€¢ listTableColumns($tableName) ā€¢ listTableConstraints($tableName) ā€¢ listTableDetails($tableName) ā€¢ listTableForeignKeys($tableName) ā€¢ listTableIndexes($tableName) ā€¢ listTables() Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 33. #sflive2010 DBAL Schema Representation $schema = new DoctrineDBALSchemaSchema(); $myTable = $schema->createTable("my_table"); $myTable->createColumn("id", "integer", array("unsigned" => true)); $myTable->createColumn("username", "string", array("length" => 32)); $myTable->setPrimaryKey(array("id")); $myTable->addUniqueIndex(array("username")); $schema->createSequence("my_table_seq"); $myForeign = $schema->createTable("my_foreign"); $myForeign->createColumn("id", "integer"); $myForeign->createColumn("user_id", "integer"); $myForeign->addForeignKeyConstraint($myTable, array("user_id"), array("id"), array("onUpdate" => "CASCADE")); $queries = $schema->toSql($myPlatform); // get queries to create this schema. $dropSchema = $schema->toDropSql($myPlatform); // get queries to safely delete this schema. Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 34. #sflive2010 Compare DBAL Schemas $comparator = new DoctrineDBALSchemaComparator(); $schemaDiff = $comparator->compare($fromSchema, $toSchema); // queries to get from one to another schema. $queries = $schemaDiff->toSql($myPlatform); $saveQueries = $schemaDiff->toSaveSql($myPlatform); Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 35. #sflive2010 Schema Management ā€¢ Extracted from ORM to DBAL ā€¢ Schema comparisons replace the migrations diff tool of Doctrine 1 Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 36. #sflive2010 Doctrine 2 Annotations <?php namespace Entities; /** * @Entity @Table(name="users") */ class User { /** @Id @Column(type="integer") @GeneratedValue */ private $id; /** @Column(length=50) */ private $name; /** @OneToOne(targetEntity="Address") */ private $address; } Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 37. #sflive2010 Things to Notice ā€¢ Entities no longer require you to extend a base class! ā€¢ Your domain model has absolutely no magic, is not imposed on by Doctrine and is deļ¬ned by raw PHP objects and normal OO programming. ā€¢ The performance improvement from this is signiļ¬cant. ā€¢ Easier to understand what is happening due to less magic occurring. As Fabien says, ā€œKill the magic...ā€ Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 38. #sflive2010 Doctrine 2 YAML EntitiesAddress: type: entity table: addresses id: id: type: integer generator: strategy: AUTO fields: street: type: string length: 255 oneToOne: user: targetEntity: User mappedBy: address Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 39. #sflive2010 Doctrine 2 XML <?xml version="1.0" encoding="UTF-8"?> <doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> <entity name="EntitiesUser" table="users"> <id name="id" type="integer"> <generator strategy="AUTO"/> </id> <field name="name" type="string" length="50"/> <one-to-one field="address" target-entity="Address"> <join-column name="address_id" referenced-column-name="id"/> </one-to-one> </entity> </doctrine-mapping> Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 40. #sflive2010 Doctrine 2 Setup ā€¢ PHP ā€œuseā€ all necessary namespaces and classes use DoctrineCommonClassLoader, DoctrineORMConfiguration, DoctrineORMEntityManager, DoctrineCommonCacheApcCache, EntitiesUser, EntitiesAddress; Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 41. #sflive2010 Doctrine 2 Setup ā€¢ Require the Doctrine ClassLoader require '../../lib/Doctrine/Common/ClassLoader.php'; Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 42. #sflive2010 Doctrine 2 Setup ā€¢ Setup autoloading for Doctrine classes ā€¢ ...core classes ā€¢ ...entity classes ā€¢ ...proxy classes $doctrineClassLoader = new ClassLoader('Doctrine', '/path/to/doctrine'); $doctrineClassLoader->register(); $entitiesClassLoader = new ClassLoader('Entities', '/path/to/entities'); $entitiesClassLoader->register(); $proxiesClassLoader = new ClassLoader('Proxies', '/path/to/proxies'); $proxiesClassLoader->register(); Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 43. #sflive2010 Doctrine 2 Setup ā€¢ Conļ¬gure your Doctrine implementation // Set up caches $config = new Configuration; $cache = new ApcCache; $config->setMetadataCacheImpl($cache); $config->setQueryCacheImpl($cache); // Proxy configuration $config->setProxyDir('/path/to/proxies/Proxies'); $config->setProxyNamespace('Proxies'); Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 44. #sflive2010 Doctrine 2 Setup ā€¢ Create your database connection and entity manager // Database connection information $connectionOptions = array( 'driver' => 'pdo_sqlite', 'path' => 'database.sqlite' ); // Create EntityManager $em = EntityManager::create($connectionOptions, $config); Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 45. #sflive2010 Doctrine 2 Setup ā€¢ In production you would lazily load the EntityManager ā€¢ Example: $em = function() { static $em; if (!$em) { $em = EntityManager::create($connectionOptions, $config); } return $em; } ā€¢ In the real world I wouldnā€™t recommend that you use the above example ā€¢ Symfony DI would take care of this for us Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 46. #sflive2010 Doctrine 2 Setup ā€¢ Now you can start using your models and persisting entities $user = new User; $user->setName('Jonathan H. Wage'); $em->persist($user); $em->flush(); Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 47. #sflive2010 Insert Performance ā€¢ Inserting 20 records with Doctrine for ($i = 0; $i < 20; ++$i) { $user = new User; $user->name = 'Jonathan H. Wage'; $em->persist($user); } $s = microtime(true); $em->flush(); $e = microtime(true); echo $e - $s; Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 48. #sflive2010 Insert Performance ā€¢ Compare it to some raw PHP code $s = microtime(true); for ($i = 0; $i < 20; ++$i) { mysql_query("INSERT INTO users (name) VALUES ('Jonathan H. Wage')", $link); } $e = microtime(true); echo $e - $s; Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 49. #sflive2010 Insert Performance ā€¢ The results might be surprising to you. Which do you think is faster? Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 50. #sflive2010 Insert Performance Doctrine 2 0.0094 seconds mysql_query 0.0165 seconds Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 51. #sflive2010 Insert Performance ā€¢ Doctrine 2 is faster than some raw PHP code? What?!?!?! HUH? ā€¢ It does a lot less, provides no features, no abstraction, etc. ā€¢ Why? The answer is transactions! Doctrine 2 manages our transactions for us and efficiently executes all inserts in a single, short transaction. The raw PHP code executes 1 transaction for each insert. Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 52. #sflive2010 Insert Performance ā€¢ Here is the same raw PHP code re-visited with proper transaction usage. $s = microtime(true); mysql_query('START TRANSACTION', $link); for ($i = 0; $i < 20; ++$i) { mysql_query("INSERT INTO users (name) VALUES ('Jonathan H. Wage')", $link); } mysql_query('COMMIT', $link); $e = microtime(true); echo $e - $s; Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 53. #sflive2010 Insert Performance ā€¢ Not trying to say Doctrine 2 is faster than raw PHP code ā€¢ Demonstrating that simple developer oversights and mis-use can cause the greatest performance problems Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 54. #sflive2010 Insert Performance ā€¢ This time around it only takes 0.0028 seconds compared to the previous 0.0165 seconds. Thatā€™s a pretty huge improvement. ā€¢ You can read more about this on the Doctrine Blog http://www.doctrine-project.org/blog/transactions-and-performance Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 55. #sflive2010 Doctrine Query Language ā€¢ DQL parser completely re-written from scratch ā€¢ ...DQL is parsed by a top down recursive descent parser that constructs an AST (abstract syntax tree). ā€¢ ...The AST is used to generate the SQL to execute for your DBMS http://www.doctrine-project.org/documentation/manual/2_0/en/dql-doctrine-query-language Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 56. #sflive2010 Doctrine Query Language ā€¢ Here is an example DQL query $q = $em->createQuery('select u from MyProjectModelUser u'); $users = $q->execute(); Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 57. #sflive2010 Doctrine Query Language ā€¢ Here is that same DQL query using the QueryBuilder API $qb = $em->createQueryBuilder() ->select('u') ->from('MyProjectModelUser', 'u'); $q = $qb->getQuery(); $users = $q->execute(); http://www.doctrine-project.org/documentation/manual/2_0/en/query-builder Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 58. #sflive2010 Doctrine Query Builder ā€¢ QueryBuilder API is the same as Doctrine_Query API in Doctrine 1 ā€¢ Query building and query execution are separated ā€¢ True builder pattern used ā€¢ QueryBuilder is used to build instances of Query ā€¢ You donā€™t execute a QueryBuilder, you get the built Query instance from the QueryBuilder and execute it Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 59. #sflive2010 Cache Drivers ā€¢ Public interface of all cache drivers ā€¢ fetch($id) - Fetches an entry from the cache. ā€¢ contains($id) - Test if an entry exists in the cache. ā€¢ save($id, $data, $lifeTime = false) - Puts data into the cache. ā€¢ delete($id) - Deletes a cache entry. Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 60. #sflive2010 Cache Drivers ā€¢ Wrap existing Symfony, ZF, etc. cache driver instances with the Doctrine interface Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 61. #sflive2010 Cache Drivers ā€¢ deleteByRegex($regex) - Deletes cache entries where the key matches a regular expression ā€¢ deleteByPreļ¬x($preļ¬x) - Deletes cache entries where the key matches a preļ¬x. ā€¢ deleteBySuffix($suffix) - Deletes cache entries where the key matches a suffix. Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 62. #sflive2010 Cache Drivers ā€¢ Each driver extends the AbstractCache class which deļ¬nes a few abstract protected methods that each of the drivers must implement to do the actual work ā€¢ _doFetch($id) ā€¢ _doContains($id) ā€¢ _doSave($id, $data, $lifeTime = false) ā€¢ _doDelete($id) Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 63. #sflive2010 APC Cache Driver ā€¢ To use the APC cache driver you must have it compiled and enabled in your php.ini $cacheDriver = new DoctrineCommonCacheApcCache(); $cacheDriver->save('cache_id', 'my_data'); Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 64. #sflive2010 Memcache Cache Driver ā€¢ To use the memcache cache driver you must have it compiled and enabled in your php.ini $memcache = new Memcache(); $memcache->connect('memcache_host', 11211); $cacheDriver = new DoctrineCommonCacheMemcacheCache(); $cacheDriver->setMemcache($memcache); $cacheDriver->save('cache_id', 'my_data'); Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 65. #sflive2010 Xcache Cache Driver ā€¢ To use the xcache cache driver you must have it compiled and enabled in your php.ini $cacheDriver = new DoctrineCommonCacheXcacheCache(); $cacheDriver->save('cache_id', 'my_data'); Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 66. #sflive2010 Result Cache ā€¢ First you need to conļ¬gure the result cache $cacheDriver = new DoctrineCommonCacheApcCache(); $config->setResultCacheImpl($cacheDriver); ā€¢ Then you can conļ¬gure each query to use the result cache or not. $query = $em->createQuery('select u from EntitiesUser u'); $query->useResultCache(true, 3600, 'my_query_name'); ā€¢ Executing this query the ļ¬rst time would populate a cache entry in $cacheDriver named my_query_name Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 67. #sflive2010 Result Cache ā€¢ Now you can clear the cache for that query by using the delete() method of the cache driver $cacheDriver->delete('my_query_name'); Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 68. #sflive2010 Command Line Interface ā€¢ Re-written command line interface to help developing with Doctrine Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 69. #sflive2010 dbal:run-sql ā€¢ Execute a manually written SQL statement ā€¢ Execute multiple SQL statements from a ļ¬le Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 70. #sflive2010 orm:clear-cache ā€¢ Clear all query, result and metadata cache ā€¢ Clear only query cache ā€¢ Clear only result cache ā€¢ Clear only metadata cache ā€¢ Clear a single queries result cache ā€¢ Clear keys that match regular expression ā€¢ Clear keys that match a preļ¬x ā€¢ Clear keys that match a suffix Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 71. #sflive2010 So now when you have a problem in Doctrine, like Symfony, you can try clearing the cache first :) Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 72. #sflive2010 orm:convert-mapping ā€¢ Convert metadata information between formats ā€¢ Convert metadata information from an existing database to any supported format (yml, xml, annotations, etc.) ā€¢ Convert mapping information from xml to yml or vice versa ā€¢ Generate PHP classes from mapping information with mutators and accessors Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 73. #sflive2010 orm:ensure-production-settings ā€¢ Verify that Doctrine is properly conļ¬gured for a production environment. ā€¢ Throws an exception when environment does not meet the production requirements Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 74. #sflive2010 orm:generate-proxies ā€¢ Generate the proxy classes for entity classes. ā€¢ 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. Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 75. #sflive2010 orm:run-dql ā€¢ Execute a DQL query from the command line Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 76. #sflive2010 orm:schema-tool ā€¢ Drop, create and update your database schema. ā€¢ --create option creates the initial tables for your schema ā€¢ --drop option drops the the tables for your schema ā€¢ --update option compares your local schema information to the database and updates it accordingly Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 77. #sflive2010 Inheritance ā€¢ Doctrine 2 fully supports inheritance. We allow the following types of inheritance: ā€¢ ...Mapped Superclasses ā€¢ ...Single Table Inheritance ā€¢ ...Class Table Inheritance Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 78. #sflive2010 Mapped Superclasses /** @MappedSuperclass */ 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 } /** @Entity */ class EntitySubClass extends MappedSuperclassBase { /** @Id @Column(type="integer") */ private $id; /** @Column(type="string") */ private $name; // ... more fields and methods } Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 79. #sflive2010 Mapped Superclasses CREATE TABLE EntitySubClass (mapped1 INTEGER NOT NULL, mapped2 TEXT NOT NULL, id INTEGER NOT NULL, name TEXT NOT NULL, related1_id INTEGER DEFAULT NULL, PRIMARY KEY(id)) http://www.doctrine-project.org/documentation/manual/2_0/en/inheritance-mapping#mapped-superclasses Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 80. #sflive2010 Single Table Inheritance /** * @Entity * @InheritanceType("SINGLE_TABLE") * @DiscriminatorColumn(name="discr", type="string") * @DiscriminatorMap({"person" = "Person", "employee" = "Employee"}) */ class Person { // ... } /** * @Entity */ class Employee extends Person { // ... } Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 81. #sflive2010 Single Table Inheritance ā€¢ All entities share one table. ā€¢ To distinguish which row represents which type in the hierarchy a so-called discriminator column is used. http://www.doctrine-project.org/documentation/manual/2_0/en/inheritance-mapping#single-table-inheritance Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 82. #sflive2010 Class Table Inheritance namespace MyProjectModel; /** * @Entity * @InheritanceType("JOINED") * @DiscriminatorColumn(name="discr", type="string") * @DiscriminatorMap({"person" = "Person", "employee" = "Employee"}) */ class Person { // ... } /** @Entity */ class Employee extends Person { // ... } http://www.doctrine-project.org/documentation/manual/2_0/en/inheritance-mapping#single-table-inheritance Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 83. #sflive2010 Class Table Inheritance ā€¢ Each class in a hierarchy is mapped to several tables: its own table and the tables of all parent classes. ā€¢ The table of a child class is linked to the table of a parent class through a foreign key constraint. ā€¢ A discriminator column is used in the topmost table of the hierarchy because this is the easiest way to achieve polymorphic queries. Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 84. #sflive2010 Batch Processing ā€¢ Doctrine 2 offers the ability to do some batch processing by taking advantage of the transactional write-behind behavior of an EntityManager Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 85. #sflive2010 Bulk Inserts ā€¢ Insert 10000 objects with a batch size of 20 $batchSize = 20; for ($i = 1; $i <= 10000; ++$i) { $user = new CmsUser; $user->setStatus('user'); $user->setUsername('user' . $i); $user->setName('Mr.Smith-' . $i); $em->persist($user); if ($i % $batchSize == 0) { $em->flush(); $em->clear(); // Detaches all objects from Doctrine! } } Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 86. #sflive2010 Bulk Update ā€¢ Bulk update with DQL $q = $em->createQuery('update MyProjectModelManager m set m.salary = m.salary * 0.9'); $numUpdated = $q->execute(); Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 87. #sflive2010 Bulk Update ā€¢ Bulk update by iterating over the results using the Query::iterate() method to avoid loading everything into memory at once $batchSize = 20; $i = 0; $q = $em->createQuery('select u from MyProjectModelUser u'); $iterableResult = $q->iterate(); foreach($iterableResult AS $row) { $user = $row[0]; $user->increaseCredit(); $user->calculateNewBonuses(); if (($i % $batchSize) == 0) { $em->flush(); // Executes all updates. $em->clear(); // Detaches all objects from Doctrine! } ++$i; } Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 88. #sflive2010 Bulk Delete ā€¢ Bulk delete with DQL $q = $em->createQuery('delete from MyProjectModelManager m where m.salary > 100000'); $numDeleted = $q->execute(); Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 89. #sflive2010 Bulk Delete ā€¢ Just like the bulk updates you can iterate over a query to avoid loading everything into memory all at once. $batchSize = 20; $i = 0; $q = $em->createQuery('select u from MyProjectModelUser u'); $iterableResult = $q->iterate(); while (($row = $iterableResult->next()) !== false) { $em->remove($row[0]); if (($i % $batchSize) == 0) { $em->flush(); // Executes all deletions. $em->clear(); // Detaches all objects from Doctrine! } ++$i; } Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 90. #sflive2010 NativeQuery + ResultSetMapping ā€¢ The NativeQuery class is used to execute raw SQL queries ā€¢ The ResultSetMapping class is used to deļ¬ne how to hydrate the results of that query Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 91. #sflive2010 NativeQuery + ResultSetMapping ā€¢ Here is a simple example $rsm = new ResultSetMapping; $rsm->addEntityResult('DoctrineTestsModelsCMSCmsUser', 'u'); $rsm->addFieldResult('u', 'id', 'id'); $rsm->addFieldResult('u', 'name', 'name'); $query = $this->_em->createNativeQuery( 'SELECT id, name FROM cms_users WHERE username = ?', $rsm ); $query->setParameter(1, 'romanb'); $users = $query->getResult(); Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 92. #sflive2010 NativeQuery + ResultSetMapping ā€¢ The result of $users would look like array( [0] => User (Object) ) Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 93. #sflive2010 NativeQuery + ResultSetMapping ā€¢ This means you will always be able to fallback to the power of raw SQL without losing the ability to hydrate the data to your entities Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  • 94. #sflive2010 Questions? 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 Doctrine 2 www.doctrine-project.org www.sensiolabs.com