2. Jonathan H. Wage
• Web developer for over a decade
• Tech junky for even longer
• Open Source Evangelist
• Published Author
• Contributes to...
• ...Doctrine
• ...Symfony
• ...and more
• Works full-time for Sensio Labs
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
3. Jonathan H. Wage
• http://www.twitter.com/jwage
• http://www.jwage.com
• http://www.facebook.com/jwage
You can contact Jonathan about Doctrine and Open-Source or for
training, consulting, application development, or business related
questions at jonathan.wage@sensio.com
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
4. Project History
• First commit April 13th 2006
• First stable version finished and Released September
1st 2008
• One of the first ORM implementations for PHP
• 1.0 is First LTS(long term support) release.
Maintained until March 1st 2010
• Integrated with many popular frameworks: Symfony,
Zend Framework, Code Igniter, etc.
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
5. The Team
• Roman S. Borschel
• Guilherme Blanco
• Benjamin Eberlei
• Bulat Shakirzyanov
• Jonathan H. Wage
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
7. Object-relational mapping (ORM, O/RM, and O/R
mapping) in computer software is a programming
technique for converting data between incompatible type
systems in object-oriented programming languages. This
creates, in effect, a "virtual object database" that can be
used from within the programming language. There are
both free and commercial packages available that
perform object-relational mapping, although some
programmers opt to create their own ORM tools.
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
9. The Doctrine1 Way
class User extends Doctrine_Record
{
public function setTableDefinition()
{
$this->hasColumn('username', 'string');
$this->hasColumn('password', 'string');
}
}
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
10. The Doctrine1 Way
$user = new User();
$user->setUsername('jwage');
$user->setPassword('password');
$user->save();
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
11. Problems
• Domain is bound to persistence layer
• Complexity of domain entities limited by
persistence layer
• $model->save() is a bottle neck for persisting
large numbers of objects
• Testing your domain model requires mocking
the persistence layer
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
12. The Doctrine2 Way
How does Doctrine2 do it?
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
13. No base class to extend
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
14. /**
* @Entity
* @Table(name="users")
*/
class User
{
/**
* @Id
*/
private $id;
/**
* @Column(type="string", length=255)
*/
private $username;
public function setUsername($username)
{
$this->username = $username;
}
// ...
}
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
15. Mapping Information
Specify your mapping information with XML, YAML or
DocBlock Annotations
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
21. Single Flush Operation
• Batch inserts
• Best to build up all object changes in your
application and flush no more than 1 or 2 times
• All managed objects are tracked and changesets
generated on flush and used to persist to
RDBMS, MongoDB, etc.
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
23. Why Transparency?
• Better performance
• Easier to cache regular PHP objects that are
not bound to the persistence layer
• Easier to test your domain, no mocking
required
• Ultimate flexibility over the complexity of your
domain entities without being imposed on by
your persistence layer
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
24. Performance
• Less abstraction on domain entities improves
performance when working with them.
• Physical accessors and getters are faster.
• Lighter and no required dependencies.
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
26. PHP 5.3 is Fast
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
27. Doctrine1
Doctrine1 benefits from using PHP 5.3. Test suite uses
30% less memory and runs 20% faster
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
28. Doctrine2 Performance
Doctrine 1.1
4.3 seconds for 5000 records
Doctrine 2.0
1.4 seconds for 5000 records
Doctrine 2.0
3.5 seconds for 10000 records
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
33. Benefits
• PHP libraries will be able to be mixed without
autoloader issues and conflict.
• Symfony2 + Doctrine2 + ZendFramework2
• Load classes from 3 different libraries with one
autoloader and one include path
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
34. Doctrine code is
divided into a few
different packages
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
35. DoctrineCommon
• Common functionality shared across packages
• Events
• Annotations Library
• Lexer Parser that is used for parsing the
Doctrine Query Language (DQL)
• Other various convenience tools
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
37. DBAL is Standalone
Use the DBAL without the ORM
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
38. DBAL History
• The Doctrine DBAL is a very powerful
project in itself
• Based off of code forked from other
projects
• PEAR MDB2
• Zend_Db
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
39. DBAL
• Using the Doctrine DBAL standalone is a good
option for your PHP projects if a fully featured
ORM is not needed
• API for performing DDL statements, executing
queries, etc.
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
40. DBAL Example
$params = array(
'driver' => 'pdo_mysql',
'host' => 'localhost',
'user' => 'root',
'password' => '',
'dbname' => 'doctrine2dbal'
);
$conn = DoctrineDBALDriverManager::getConnection($params);
Execute queries against your database using $conn. The
API is very similar to that of PDO and adds some extra
conveniences.
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
45. DoctrineORM
• Object Relational Mapper
• Built on top of the DBAL
• Provides transparent domain object persistence
to relational databases
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
46. Persisting to Other
Databases
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
48. DoctrineODMMongoDB
• Provides transparent domain object persistence
to MongoDB
• Same architecture and design as the ORM
• New addition to the Doctrine project
• Umbrella of project widened to offer Doctrine
style persistence layers for other popular open
source databases.
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
49. Architecture
The architecture of the Doctrine object persistence
layers
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
50. The ObjectManager
EntityManager and DocumentManager
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
51. API
Simple API for managing the persistent state of objects
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
52. Object States
• A NEW object instance has no persistent identity, and is not yet
associated with a ObjectManager (i.e. those just created with the "new"
operator).
• A MANAGED object instance is an instance with a persistent identity
that is associated with an ObjectManager and whose persistence is thus
managed.
• A DETACHED object instance is an instance with a persistent
identity that is not (or no longer) associated with an ObjectManager.
• A REMOVED object instance is an instance with a persistent identity,
associated with an ObjectManager, that will be removed from the
database upon transaction commit.
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
56. Persisting
$user = new User();
$user->setUsername('jwage');
$user->setPassword('password');
// Persist the new object so it is
// saved to the database
$em->persist($user);
$em->flush();
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
64. AST = Abstract Syntax Tree
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
65. Tree representation of the
syntactical structure of a
source language
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
66. PHP class names of DQL
parser directly represent
the language itself
• OrderByClause.php
• SelectClause.php
• SelectExpression.php
• Subselect.php
• DeleteClause.php
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
67. • Easy to use
• Easy to expand and add new features
• Easy to use and understand the
parsing of a DQL string
• Expand the DQL parser with your
own functionality and add to the
DQL language
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
68. Parsing of DQL is Cached
In a production environment a DQL query is only ever
parsed and transformed to SQL once so performance
is not an issue.
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
69. Sample DQL Query
$query = $em->createQuery(
'SELECT u, g, FROM User u ' .
'LEFT JOIN u.Groups g ' .
'ORDER BY u.name ASC, g.name ASC'
);
$users = $query->execute();
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
72. Result Cache
$query = $em->createQuery('SELECT u FROM ModelsUser u');
$query->useResultCache(true, 3600, 'user_query');
$users = $query->execute();
Execute query again and the results are retrieved from the cache
$users = $query->execute();
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
73. Symfony2 Integration
The Doctrine features are tightly integrated with
Symfony2
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
74. Enabling the DBAL
Enable the DBAL in your application configuration
# config/config.yml
doctrine.dbal:
driver: PDOMySql
dbname: Symfony2
user: root
password: null
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
75. Using the DBAL
Use the DBAL connection in your controllers
class UserController extends Controller
{
public function indexAction()
{
$conn = $this->container->getService('database_connection');
$users = $conn->fetchAll('SELECT * FROM users');
}
}
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
76. Enabling the ORM
Enable the ORM in your application configuration
# config/config.yml
doctrine.orm: ~
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
77. Creating an Entity
Application/HelloBundle/Entity/User.php
namespace ApplicationHelloBundleEntity;
/**
* @Entity
*/
class User
{
/** @Id */
public $id;
/** @Column(type="string", length="255") */
public $username;
/** @Column(type="string", length="255") */
public $password;
}
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
79. Using the ORM
Use the ORM EntityManager in your controllers
use ApplicationHelloBundleEntitiesUser;
class UserController extends Controller
{
public function createAction()
{
$user = new User();
$user->setName('Jonathan H. Wage');
$em = $this->container->getService('doctrine.orm.entity_manager');
$em->persist($user);
$em->flush();
// ...
}
}
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
80. Conclusion
Why use an ORM?
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
81. Encapsulation
Encapsulate all your domain logic in one place, in an
object oriented way
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
82. Maintainability
The organization of the domain logic in an OO way
improves maintainability
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
83. Testability
Keeping a clean OO domain model makes your
business logic easily testable for improved stability
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
84. Portability
Write portable and thin application controller code and
fat models.
Doctrine 2.0 www.doctrine-project.org www.sensiolabs.org
85. Questions?
Jonathan H. Wage
jonwage@gmail.com
http://www.twitter.com/jwage
+1 615 513 9185
sensiolabs.com | doctrine-project.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.0 www.doctrine-project.org www.sensiolabs.org