Doctrine is not just an ORM for Relational Databases post
Posted on 2014-01-18 by jwage
In April of 2010 the first commit for the Doctrine MongoDB ODM project was made. I was experimenting with MongoDB at the time and I wanted to see how difficult it would be to build a version of Doctrine for MongoDB.
Up until the MongoDB ODM, Doctrine was solely a project built around the DBAL/ORM and was advertised as such. In May of 2010 we decided to widen the scope of the project so that we could host libraries like the MongoDB ODM. This change led to a spur of new contributors and development and we now have several object mappers developed under Doctrine and things are more active than ever.
Below is an overview of all the libraries underneath the Doctrine project.
Common Shared Libraries
Doctrine Common contains some base functionality and interfaces you need in order to create a Doctrine style object mapper. All of our mapper projects follow the same Doctrine\Common\Persistence
interfaces. Here are the ObjectManager
and ObjectRepository
interfaces:
<?php
namespace Doctrine\Common\Persistence
interface ObjectManager
{
public function find($className, $id);
public function persist($object);
public function remove($object);
public function merge($object);
public function clear($objectName = null);
public function detach($object);
public function refresh($object);
public function flush();
public function getRepository($className);
}
interface ObjectRepository
{
public function find($id);
public function findAll();
public function findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null);
public function findOneBy(array $criteria);
}
Doctrine Collections is a library that contains classes for working with arrays of data. Here is an example using the simple Doctrine\Common\Collections\ArrayCollection
class:
<?php
$data = new \Doctrine\Common\Collections\ArrayCollection(array(1, 2, 3));
$data = $data->filter(function($count) { return $count > 1; });
Doctrine Annotations is a library that allows you to parse structured information out of a doc block.
Imagine you have a class with a doc block like the following:
<?php
/** @Foo(bar="value") */
class User
{
}
You can parse the information out of the doc block for User
easily. Define a new annotation object:
<?php
/**
* @Annotation
* @Target("CLASS")
*/
class Foo
{
/** @var string */
public $bar;
}
Now you can get instances of Foo
defined on the User
:
<?php
$reflClass = new ReflectionClass('User');
$reader = new \Doctrine\Common\Annotations\AnnotationReader();
$classAnnotations = $reader->getClassAnnotations($reflClass);
foreach ($classAnnotations AS $annot) {
if ($annot instanceof Foo) {
echo $annot->bar; // prints "value";
}
}
Doctrine Inflector is a library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.
<?php
$camelCase = 'camelCase';
$table = \Doctrine\Common\Inflector::tableize($camelCase);
echo $table; // camel_case
Doctrine Lexer is a library that can be used in Top-Down, Recursive Descent Parsers. This lexer is used in Doctrine Annotations and in Doctrine ORM (DQL).
Here is what the AbstractLexer
provided by Doctrine looks like:
<?php
namespace Doctrine\Common\Lexer;
abstract class AbstractLexer
{
public function setInput($input);
public function reset();
public function resetPeek();
public function resetPosition($position = 0);
public function isNextToken($token);
public function isNextTokenAny(array $tokens);
public function moveNext();
public function skipUntil($type);
public function isA($value, $token);
public function peek();
public function glimpse();
public function getLiteral($token);
abstract protected function getCatchablePatterns();
abstract protected function getNonCatchablePatterns();
abstract protected function getType(&$value);
}
To implement a lexer just extend the Doctrine\Common\Lexer\AbstractParser
class and implement the getCatchablePatterns
, getNonCatchablePatterns
, and getType
methods. Here is a very simple example lexer implementation named CharacterTypeLexer
. It tokenizes a string to T_UPPER
, T_LOWER
and T_NUMER
:
<?php
use Doctrine\Common\Lexer\AbstractParser;
class CharacterTypeLexer extends AbstractLexer
{
const T_UPPER = 1;
const T_LOWER = 2;
const T_NUMBER = 3;
protected function getCatchablePatterns()
{
return array(
'[a-bA-Z0-9]',
);
}
protected function getNonCatchablePatterns()
{
return array();
}
protected function getType(&$value)
{
if (is_numeric($value)) {
return self::T_NUMBER;
}
if (strtoupper($value) === $value) {
return self::T_UPPER;
}
if (strtolower($value) === $value) {
return self::T_LOWER;
}
}
}
Use CharacterTypeLexer
to extract an array of upper case characters:
<?php
class UpperCaseCharacterExtracter
{
private $lexer;
public function __construct(CharacterTypeLexer $lexer)
{
$this->lexer = $lexer;
}
public function getUpperCaseCharacters($string)
{
$this->lexer->setInput($string);
$this->lexer->moveNext();
$upperCaseChars = array();
while (true) {
if (!$this->lexer->lookahead) {
break;
}
$this->lexer->moveNext();
if ($this->lexer->token['type'] === CharacterTypeLexer::T_UPPER) {
$upperCaseChars[] = $this->lexer->token['value'];
}
}
return $upperCaseChars;
}
}
$upperCaseCharacterExtractor = new UpperCaseCharacterExtracter(new CharacterTypeLexer());
$upperCaseCharacters = $upperCaseCharacterExtractor->getUpperCaseCharacters('1aBcdEfgHiJ12');
print_r($upperCaseCharacters);
The variable $upperCaseCharacters
contains all of the upper case characters:
Array
(
[0] => B
[1] => E
[2] => H
[3] => J
)
Doctrine Cache is a library that provides an interface for caching data. It comes with implementations for some of the most popular caching data stores. Here is what the Cache
interface looks like:
<?php
namespace Doctrine\Common\Cache;
interface Cache
{
function fetch($id);
function contains($id);
function save($id, $data, $lifeTime = 0);
function delete($id);
function getStats();
}
Here is an example using memcache:
<?php
$memcache = new \Memcache();
$cache = new \Doctrine\Common\Cache\MemcacheCache();
$cache->setMemcache($memcache);
$cache->set('key', 'value');
echo $cache->get('key') // prints "value"
Other supported drivers are:
- APC
- Couchbase
- Filesystem
- Memcached
- MongoDB
- PhpFile
- Redis
- Riak
- WinCache
- Xcache
- ZendData
Database Abstraction Layers
Doctrine DBAL is a library that provides an abstraction layer for relational databases in PHP. Read Doctrine DBAL: PHP Database Abstraction Layer blog post for more information on the DBAL.
Doctrine MongoDB is a library that provides an abstraction layer on top of the PHP MongoDB PECL extension. It provides some additional functionality and abstractions to make working with MongoDB easier.
Doctrine CouchDB Client is a library that provides a connection abstraction to CouchDB by wrapping around the CouchDB HTTP API.
<?php
$client = \Doctrine\CouchDB\CouchDBClient::create();
array($id, $rev) = $client->postDocument(array('foo' => 'bar'));
$client->putDocument(array('foo' => 'baz'), $id, $rev);
$doc = $client->findDocument($id);
Object Mappers
The object mappers are where all the pieces come together. The object mappers provide transparent persistence for PHP objects. As mentioned above, they all implement the common interfaces from Doctrine\Common
so working with each of them is generally the same. You have an ObjectManager
to manage the persistent state of your domain objects:
<?php
$user = new User();
$user->setId(1);
$user->setUsername('jwage');
$om = $this->getYourObjectManager();
$om->persist($user);
$om->flush(); // insert the new document
Then you can find that object later and modify it:
<?php
$user = $om->find('User', 1);
echo $user->getUsername(); // prints "jwage"
$user->setUsername('jonwage'); // change the obj in memory
$om->flush(); // updates the object in the database
You can find more information about the supported object mappers below:
Doctrine ORM provides persistence for PHP objects to relational database.
Doctrine CouchDB ODM provides persistence for PHP objects to CouchDB.
Doctrine PHPCR (Content Repository) ODM provides persistence to a backend like Jackalope or Midgard2. This is a specialized object mapper for dealing with data designed for building content websites. Think of this like a backend for a CMS (Content Management System).
Doctrine MongoDB ODM provides persistence for PHP objects to MongoDB. You can read more about the MongoDB ODM here.
Doctrine OrientDB ODM provides persistence for PHP objects to OrientDB.
Categories: articles