Doctrine MongoDB ODM is an object document mapper for PHP that provides tools for managing object persistence with MongoDB. It allows developers to work with MongoDB documents as objects and provides a query API and change tracking functionality to make common operations like inserting, updating, and deleting documents straightforward. Doctrine abstracts away the low-level MongoDB driver to allow developers to work with documents and references between documents using familiar object-oriented patterns.
3. What is Doctrine?
• Open source PHP project started in 2006
• Relational database abstraction layer.
• mysql, oracle, pgsql, sqlite, etc.
• Object persistence layers for RDBMS,
MongoDB, etc.
• Other database related functionalities.
http://www.doctrine-project.org
Doctrine MongoDB ODM www.doctrine-project.org www.sensiolabs.org
4. What is MongoDB?
• Key-Value document based storage
system.
• Bridge between traditional relational
databases and key-value data stores.
http://www.mongodb.org
Doctrine MongoDB ODM www.doctrine-project.org www.sensiolabs.org
10. Inserting Documents
Insert a new user document and echo the newly generated id
$user = array(
'username' => 'jwage',
'password' => md5('changeme')
'active' => true
);
$coll->insert($user);
echo $user['_id'];
Doctrine MongoDB ODM www.doctrine-project.org www.sensiolabs.org
11. Updating Documents
Update username and password and save the whole document
$user = $coll->findOne(array('username' => 'jwage'));
$user['username'] = 'jonwage';
$user['password'] = md5('newpassword');
$coll->save($user);
Doctrine MongoDB ODM www.doctrine-project.org www.sensiolabs.org
12. Atomic Updates
• Faster than saving the entire document.
• Safer than updating the entire document.
• Updates are done in place and are atomic.
Doctrine MongoDB ODM www.doctrine-project.org www.sensiolabs.org
14. Atomic Updates
Many other atomic operators exist for manipulating a documents data
• $inc - increments field by the number value
• $set - sets field to value
• $unset - deletes a given field
• $push - appends value to an array
• $pushAll - appends multiple values to an array
• $addToSet - appends multiple values to an array that don’t already exist in the
array
• $pop - removes the last element in an array
• $pull - removes all occurrences of a value from an array
• $pullAll - removes all occurrences of multiple values from an array
Doctrine MongoDB ODM www.doctrine-project.org www.sensiolabs.org
17. DocumentManager
• Abstraction on top of the PHP Mongo
class
• Manages the persistent state of PHP
objects
• Implements UnitOfWork for change
tracking
http://martinfowler.com/eaaCatalog/unitOfWork.html
Doctrine MongoDB ODM www.doctrine-project.org www.sensiolabs.org
18. Document States
• A NEW document instance has no persistent identity, and is not yet
associated with a DocumentManager (i.e. those just created with the
"new" operator).
• A MANAGED document instance is an instance with a persistent
identity that is associated with an DocumentManager and whose
persistence is thus managed.
• A DETACHED document instance is an instance with a persistent
identity that is not (or no longer) associated with an
DocumentManager.
• A REMOVED document instance is an instance with a persistent
identity, associated with an DocumentManager, that will be removed
from the database upon transaction commit.
Doctrine MongoDB ODM www.doctrine-project.org www.sensiolabs.org
19. DocumentManager
Create your DocumentManager instance for managing object persistence
$config = new DoctrineODMMongoDBConfiguration();
$config->setMetadataCacheImpl(new DoctrineCommonCacheArrayCache);
$driverImpl = $config->newDefaultAnnotationDriver(array(__DIR__."/Documents"));
$config->setMetadataDriverImpl($driverImpl);
$config->setProxyDir(__DIR__ . '/Proxies');
$config->setProxyNamespace('Proxies');
$dm = DoctrineORMDocumentManager::create($mongo, $config);
Wraps around existing $mongo connection
Doctrine MongoDB ODM www.doctrine-project.org www.sensiolabs.org
20. Defining Document
A document is just a regular ole’ PHP class
class User
{
private $id;
private $username;
private $password;
public function getId()
{
return $this->id;
}
public function getUsername()
{
return $this->username;
}
public function setUsername($username)
{
$this->username = $username;
}
public function getPassword()
{
return $this->password;
}
public function setPassword($password)
{
$this->password = md5($password);
}
}
Doctrine MongoDB ODM www.doctrine-project.org www.sensiolabs.org
22. Ready to Go
Doctrine now knows about this document and is able
to manage its persistent state
Doctrine MongoDB ODM www.doctrine-project.org www.sensiolabs.org
27. Query API
Fluent OO Query API
Doctrine MongoDB ODM www.doctrine-project.org www.sensiolabs.org
28. Querying MongoDB
Directly
// Get user array directly from mongo
$user = $mongo->db->users->findOne(array('username' => 'jwage'));
Returns an array of information and not a User object
Doctrine MongoDB ODM www.doctrine-project.org www.sensiolabs.org
29. Querying Through
Doctrine
// Get user class instance through Doctrine
$user = $dm->findOne('User', array('username' => 'jwage'));
Going through Doctrine gives you managed objects back instead of arrays
Doctrine MongoDB ODM www.doctrine-project.org www.sensiolabs.org
30. Querying Through
Doctrine Query API
// Get user class instance through Doctrine Query API
$user = $dm->createQuery('User')
->field('username')->equals('jwage')
->getSingleResult();
Query for same user using the Query API
Doctrine MongoDB ODM www.doctrine-project.org www.sensiolabs.org
31. Querying Through
Doctrine Query API
// Find posts within a range of dates
$posts = $dm->createQuery('Post')
->field('createdAt')->range($startDate, $endDate)
->execute();
Doctrine MongoDB ODM www.doctrine-project.org www.sensiolabs.org
44. References
MongoDB does not have joins or foreign keys but you
can still store references to other documents and
resolve the references in your application code.
Doctrine abstracts the handling of referneces for you
so working with them is seamless.
Doctrine MongoDB ODM www.doctrine-project.org www.sensiolabs.org
45. Organization
/** @Document */
class Organization
{
/** @Id */
private $id;
/** @String */
private $name;
/** @ReferenceMany(targetDocument="User") */
private $users = array();
public function setName($name)
{
$this->name = $name;
}
public function addUser(User $user)
{
$this->users[] = $user;
}
}
Doctrine MongoDB ODM www.doctrine-project.org www.sensiolabs.org
46. User
/** @Document */
class User
{
/** @Id */
private $id;
/** @String */
private $name;
/** @ReferenceOne(targetDocument="Organization") */
private $organization;
public function setName($name)
{
$this->name = $name;
}
public function setOrganization(Organization $organization)
{
$this->organization = $organization;
$organization->addUser($this);
}
}
Doctrine MongoDB ODM www.doctrine-project.org www.sensiolabs.org
47. $organization = new Organization();
$organization->setName('Sensio Labs');
$user = new User();
$user->setName('Jonathan H. Wage');
$user->setOrganization($organization);
$dm->persist($organization);
$dm->persist($user);
$dm->flush();
Doctrine MongoDB ODM www.doctrine-project.org www.sensiolabs.org
54. UnitOfWork
• Tracks changes in objects between flushes
• Maintains copy of old values to compare
new values to
• Changesets computed and persisted in
the most efficient way using atomic
operators $inc, $set, $unset, $pullAll,
$pushAll, etc.
Doctrine MongoDB ODM www.doctrine-project.org www.sensiolabs.org
61. Paging Results
$users = $dm->query('find all FROM User limit 30 skip 30');
Doctrine MongoDB ODM www.doctrine-project.org www.sensiolabs.org
62. Selecting Slice of
Embedded Documents
$post = $dm->query('find title, comments limit 20 skip 10 FROM
BlogPost WHERE id = ?', array($id));
Doctrine MongoDB ODM www.doctrine-project.org www.sensiolabs.org
63. Other Examples
// Find all posts greater than or equal to a date
$posts = $dm->query('find all FROM BlogPost WHERE createdAt >= ?',
array($date));
// Find all posts sorted by created at desc
$posts = $dm->query('find all FROM BlogPost sort createdAt desc');
// Update user
$dm->query('update DocumentsUser set password = ? where username = ?',
array('newpassword', 'jwage'));
Doctrine MongoDB ODM www.doctrine-project.org www.sensiolabs.org
65. “A lifecycle event is a regular event with the additional
feature of providing a mechanism to register direct
callbacks inside the corresponding document classes
that are executed when the lifecycle event occurs.”
http://www.doctrine-project.org/projects/mongodb_odm/1.0/docs/reference/events/en#lifecycle-callbacks
Doctrine MongoDB ODM www.doctrine-project.org www.sensiolabs.org
66. • preRemove - The preRemove event occurs for a given document before the
respective DocumentManager remove operation for that document is
executed.
• postRemove - The postRemove event occurs for an document after the
document has been removed. It will be invoked after the database delete
operations.
• prePersist - The prePersist event occurs for a given document before the
respective DocumentManager persist operation for that document is executed.
• postPersist - The postPersist event occurs for an document after the
document has been made persistent. It will be invoked after the database insert
operations. Generated primary key values are available in the postPersist event.
• preUpdate - The preUpdate event occurs before the database update
operations to document data.
• postUpdate - The postUpdate event occurs after the database update
operations to document data.
• postLoad - The postLoad event occurs for an document after the document
has been loaded into the current DocumentManager from the database or after
the refresh operation has been applied to it.
Doctrine MongoDB ODM www.doctrine-project.org www.sensiolabs.org
70. Initial Document
/**
* @Document
*/
class User
{
/** @Id */
public $id;
/** @String */
public $name;
}
Doctrine MongoDB ODM www.doctrine-project.org www.sensiolabs.org
71. New Document
/**
* @Document
*/
class User
{
/** @Id */
public $id;
/** @String */
public $firstName;
/** @String */
public $lastName;
}
Doctrine MongoDB ODM www.doctrine-project.org www.sensiolabs.org
72. Migrate Documents
With Old Field Name
/**
* @Document
* @HasLifecycleCallbacks
*/
class User
{
/** @Id */
public $id;
/** @String */
public $firstName;
/** @String */
public $lastName;
/** @PreLoad */
public function preLoad(array &$data)
{
if (isset($data['name']))
{
$e = explode(' ', $data['name']);
unset($data['name']);
$data['firstName'] = $e[0];
$data['lastName'] = $e[1];
}
}
Doctrine MongoDB ODM www.doctrine-project.org www.sensiolabs.org
73. Questions?
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 MongoDB ODM www.doctrine-project.org www.sensiolabs.org