ProxyManager, BjyAuthorize, AssetManager, ZeffMu, ZfrRest, OcraDiCompiler, OcraServiceManager, OcraCachedViewResolver, DoctrineModule, DoctrineORMModule, DoctrineMongoODMModule, VersionEyeModule
An incubator for persistence-oriented libraries
Doctrine ORM is an Object Relational Mapper
It is inspired by Hibernate and the JPA (JSR-317)
It is based on a DBAL (DataBase Abstraction Layer)
Allows developers to save and load POPO with SQL
An ORM gives you the impression that you are working with a "virtual" graph composed by objects...
... backed by any persistence layer!
Simpler:
Doctrine works with simple objects (POPO)
Objects with an identifier are defined as Entities
namespace Application\Entity;
use Doctrine\ORM\Mapping as ORM;
/** @ORM\Entity */
class User {
/**
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
* @ORM\Column(type="integer")
*/
protected $id;
/** @ORM\Column(type="string") */
protected $name;
// getters/setters
}
php public/index.php orm:validate-schema
php public/index.php orm:schema-tool:create
$objectManager = \Doctrine\ORM\EntityManager::create(/* yadda */);
$objectManager = \Doctrine\ORM\EntityManager::create(/* yadda */);
$user = new \Application\Entity\User();
$user->setName('Zaphod Beeblebrox');
$objectManager->persist($user);
$objectManager->flush();
var_dump($user->getId());
$user = new \Application\Entity\User();
$user->setName('Arthur Dent');
$objectManager->persist($user); // $user is now "managed"
$objectManager->flush(); // commit changes to db
var_dump($user->getId()); // 1
$ford = $objectManager
->getRepository('Application\Entity\User')
->findOneBy(array('name' => 'Ford Prefect'));
$marvin = $objectManager
->getRepository('Application\Entity\User')
->findOneBy(array('name' => 'Marvin'));
$marvin->setName('Marvin the Paranoid Android');
$objectManager->flush();
$president = $objectManager
->getRepository('Application\Entity\User')
->findOneBy(array('name' => 'Zaphod Beeblebrox'));
$objectManager->remove($president);
$objectManager->flush();
namespace Application\Entity;
use Doctrine\ORM\Mapping as ORM;
/** @ORM\Entity */
class Address {
/**
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
* @ORM\Column(type="integer")
*/
protected $id;
/** @ORM\Column(type="string") */
protected $country;
// getters/setters
}
class User {
// ...
/** @ORM\ManyToOne(targetEntity="Address") */
protected $address;
// ...
}
$user = new User();
$user->setName('Arthur Dent');
$objectManager->persist($user);
$address = new Address();
$address->setCountry('UK');
$objectManager->persist($address);
$user->setAddress($address);
$objectManager->flush();
$user = $objectManager
->getRepository('Application\Entity\User')
->findOneBy(array('name' => 'Arthur Dent'));
echo $user->getAddress()->getCountry(); // UK
class User {
// ...
/** @ORM\ManyToMany(targetEntity="User") */
protected $friends;
public function __construct() {
$this->friends = new \Doctrine\Common\Collections\ArrayCollection();
}
// ...
}
$arthur = new User();
$arthur->setName('Arthur Dent');
$objectManager->persist($arthur);
$trillian = new User();
$trillian->setName('Tricia Marie McMillan');
$objectManager->persist($trillian);
$zaphod = new User();
$zaphod->setName('Zaphod Beeblebrox');
$objectManager->persist($zaphod);
$arthur->getFriends()->add($trillian);
$trillian->getFriends()->add($zaphod);
$objectManager->flush();
$arthur = $objectManager
->getRepository('Application\Entity\User')
->findOneBy(array('name' => 'Arthur Dent'));
foreach ($arthur->getFriends() as $friend) {
echo $friend->getName() . "\n";
}
Note: Trillian doesn't see Arthur as a friend
Note2: Zaphod doesn't see Trillian as a friend
DoctrineModule
basic common functionality
DoctrineORMModule
ORM/SQL Connection
DoctrineMongoODMModule
ODM/MongoDB Connection
php composer.phar require doctrine/doctrine-orm-module:0.7.*
php composer.phar require zendframework/zend-developer-tools:dev-master
config/application.config.php
return [
'modules' => [
'ZendDeveloperTools',
'DoctrineModule',
'DoctrineORMModule',
'Application',
],
// [...]
];
module/Application/config/module.config.php
return [
'doctrine' => [
'driver' => [
'application_entities' => [
'class' =>'Doctrine\ORM\Mapping\Driver\AnnotationDriver',
'cache' => 'array',
'paths' => [__DIR__ . '/../src/Application/Entity']
],
'orm_default' => [
'drivers' => [
'Application\Entity' => 'application_entities'
]
]]], // [...]
config/autoload/doctrine.local.php
return [
'doctrine' => [
'connection' => [
'orm_default' => [
'driverClass' =>'Doctrine\DBAL\Driver\PDOMySql\Driver',
'params' => [
'host' => 'localhost',
'port' => '3306',
'user' => 'username',
'password' => 'password',
'dbname' => 'database',
]]]]];
module/Application/src/Application/Controller/IndexController.php
public function indexAction() {
$objectManager = $this
->getServiceLocator()
->get('Doctrine\ORM\EntityManager');
$user = new \Application\Entity\User();
$user->setFullName('Slartibarfast');
$objectManager->persist($user);
$objectManager->flush();
die(var_dump($user->getId()));
}
See what your entities look like in a graph:
use Doctrine\Common\Collections\ArrayCollection;
use DoctrineModule\Paginator\Adapter\Collection as Adapter;
use Zend\Paginator\Paginator;
// Create a Doctrine Collection
$collection = new ArrayCollection(range(1, 101));
// Create the paginator itself
$paginator = new Paginator(new Adapter($collection));
$paginator
->setCurrentPageNumber(1)
->setItemCountPerPage(5);
use DoctrineORMModule\Paginator\Adapter\DoctrinePaginator;
use Doctrine\ORM\Tools\Pagination\Paginator as ORMPaginator;
use Zend\Paginator\Paginator;
// Create a Doctrine Collection
$query = $em->createQuery('SELECT u FROM User u JOIN u.friends f');
// Create the paginator itself
$paginator = new Paginator(
new DoctrinePaginator(new ORMPaginator($query))
);
$paginator
->setCurrentPageNumber(1)
->setItemCountPerPage(5);
$repository = $objectManager
->getRepository('Application\Entity\User');
$validator = new \DoctrineModule\Validator\ObjectExists([
'object_repository' => $repository,
'fields' => ['email'],
]);
var_dump($validator->isValid('test@example.com'));
var_dump($validator->isValid(['email' => 'test@example.com']));
$zendCache = new \Zend\Cache\Storage\Adapter\Memory();
$cache = new \DoctrineModule\Cache\ZendStorageCache($zendCache);
$doctrineCache = new \Doctrine\Common\Cache\ArrayCache();
$options = new \Zend\Cache\Storage\Adapter\AdapterOptions();
$cache = new \DoctrineModule\Cache\DoctrineCacheStorage(
$options,
$doctrineCache
);
use DoctrineModule\Stdlib\Hydrator\DoctrineObject;
$hydrator = new DoctrineObject($objectManager, 'Application\Entity\City');
$city = new City();
$data = array('name' => 'Béziers');
$city = $hydrator->hydrate($data, $city);
echo $city->getName(); // prints "Béziers"
$dataArray = $hydrator->extract($city);
echo $dataArray['name']; // prints "Béziers"
$form->add([
'type' => 'DoctrineModule\Form\Element\ObjectSelect',
'name' => 'user',
'options' => [
'object_manager' => $objectManager,
'target_class' => 'Module\Entity\User',
'property' => 'fullName',
'is_method' => true,
'find_method' => [
'name' => 'findBy',
'params' => array(
'criteria' => ['active' => 1],
'orderBy' => ['lastName' => 'ASC'],
],
],
],
]);
Works with MongoDB ODM too!
CouchDB ODM / PHPCR ODM / OrientDB ODM
Data, keep them simple!
No logic, just simple checks
Only aware only of themselves + associations
If you stick with using only doctrine/common API,
you can switch between
ORM /
MongoDB ODM / CouchDB ODM /
PHPCR ODM / OrientDB ODM
Instead of
Doctrine\ORM\EntityManager
use
Doctrine\Common\Persistence\ObjectManager
Instead of
Doctrine\ORM\EntityRepository
use
Doctrine\Common\Persistence\ObjectRepository
Doctrine comes with a powerful collections API
OOP API for array-like data structures
Collections provide a Criteria API
Abstracts the problem of "searching"
Filter virtually any kind of data structure
use Doctrine\Common\Collections\Criteria;
use Doctrine\Common\Collections\ArrayCollection;
$collection = new ArrayCollection(array($user1, $user2, $user3));
$criteria = new Criteria();
$criteria->andWhere(
$criteria->expr()->gt(
'lastLogin',
new \DateTime('-1 day')
)
);
$recentVisitors = $collection->matching($criteria);
$recentVisitors = $em
->getRepository('Application\Entity\Users')
->matching($criteria);
Works in ORM Repositories, Collections, etc...
Same criteria for different persistence layers (ORM, ODM, Memory, ElasticSearch, cache...)
Criteria objects make code readable!
Allows you to define your own RecentUsersCriteria
or InactiveUsersCriteria
...
$frequentVisitors = $em
->getRepository('Application\Entity\Users')
->matching(new FrequentVisitorsCriteria());
Use Dependency Injection, luke!
class MyService {
public function __construct(ObjectManager $objectManager) {
// [...]
}
}
'factories' => [
'my_service' => function ($serviceLocator) {
$objectManager = $serviceLocator->get('Doctrine\ORM\EntityManager');
return new MyService($objectManager);
}
],
Filtering data when saved to DB
Validating data when saved to DB
Saving files when records are saved to DB
Using DB-level errors to check input validity
An ObjectManager works under the assumption that managed objects are valid!
Assign values to your entities only when data is valid!