SlideShare a Scribd company logo
1 of 48
ZF & Doctrine 2 ODM


                  Doctrine
WHO IS RYAN MAUGER?
ā€¢   Zend Framework Contributor

ā€¢   Zend Framework CR Team Member

ā€¢   Co-Author of Zend Framework 2 in Action (With Rob Allen)

ā€¢   Technical Editor for Zend Framework: A Beginners Guide

ā€¢   Community Supporter

ā€¢   Zend Certiļ¬ed PHP5 Engineer

ā€¢   Lead Developer at Lupimedia and trainer at Lupijuice
What is the ODM?
What is the ODM?
 Object Document Mapper
What is the ODM?
 Object Document Mapper



    Similar to an ORM
What is the ODM?
     Object Document Mapper



        Similar to an ORM
But works with a Document Database
What is the ODM?
     Object Document Mapper



        Similar to an ORM
But works with a Document Database
Whats the advantage?


ā€¢ Schema-less design (no complicated ALTER
 TABLE statements, just save your data!

ā€¢ Works with JSON objects, familiar with what
 your already doing

ā€¢ Simple!
Whats the advantage?


ā€¢ Schema-less design (no complicated ALTER
  TABLE statements, just save your data!

ā€¢ Works with JSON objects, familiar with what
  your already doing

ā€¢ Simple! (at least to get started)
Whats the advantage?
                     Doctrine 2

ā€¢ Uses the Data Mapper pattern
ā€¢ Simpliļ¬es your domain, removes the
 persistence logic

ā€¢ Entities are free to do their job
ā€¢ Deļ¬nes a framework by which your domain
 model will work, improving consistency
Getting started with the
                   ODM

Persistence operations revolve around the Document Manager


 Mapping of properties is carried out through annotations in
       your entities, or through xml/yaml mappings
<?php
namespace ApplicationBlog;

/**
  * @Document(db="blog", collection="posts")
  */
class Post
{
     /**
      * @Id
      */
     private $id;
                                                                     An example entity
    /**
     * @Field(type="string")
     */
    private $title;

    /**
     * @String
     */
                                                                     Properties
    private $content;

    /**                                                               /**
     * @EmbedMany(targetDocument="ApplicationBlogComment")
     */                                                                * @Id
    private $comments = array();
                                                                       */
    public function getId()                                            private $id;
    {
       return $this->id;
    }                                                                  /**
    public function setId($id)                                          * @Field(type="string")
    {
       $this->id = (string) $id;                                        */
       return $this;                                                   private $title;
    }

    public function getTitle()
    {
                                                                       /**
       return $this->title;                                             * @String
    }
                                                                        */
    public function setTitle($title)                                   private $content;
    {
       $this->title = (string) $title;

    }
       return $this;                                                   /**
                                                                        * @EmbedMany(targetDocument="ApplicationBlogComment")
    public function getContent()
    {                                                                   */
       return $this->content;                                          private $comments = array();
    }

    public function setContent($content)
    {
       $this->content = (string) $content;
       return $this;
    }

    public function getComments()
    {
       return $this->comments;
    }

    public function addComment(ApplicationBlogComment $comment)
    {
       $this->comments[] = $comment;
       return $this;
    }
}
<?php
namespace ApplicationBlog;

/**
  * @Document(db="blog", collection="posts")
  */
class Post
{
     /**
      * @Id
      */
     private $id;
                                                                     An example entity
    /**
     * @Field(type="string")
     */
    private $title;

    /**
     * @String
     */
                                                                     Methods
    private $content;

    /**
     * @EmbedMany(targetDocument="ApplicationBlogComment")
                                                                      public function getContent()
     */                                                               {
    private $comments = array();
                                                                          return $this->content;
    public function getId()                                           }
    {
       return $this->id;
    }                                                                 public function setContent($content)
    public function setId($id)                                        {
    {
       $this->id = (string) $id;                                          $this->content = (string) $content;
       return $this;                                                      return $this;
    }
                                                                      }
    public function getTitle()
    {
       return $this->title;                                           public function getComments()
    }
                                                                      {
    public function setTitle($title)                                      return $this->comments;
    {
       $this->title = (string) $title;                                }
       return $this;
    }
                                                                      public function addComment(ApplicationBlogComment $comment)
    public function getContent()
    {                                                                 {
       return $this->content;                                             $this->comments[] = $comment;
    }
                                                                          return $this;
    public function setContent($content)
    {
                                                                      }
       $this->content = (string) $content;
       return $this;
    }

    public function getComments()
    {
       return $this->comments;
    }

    public function addComment(ApplicationBlogComment $comment)
    {
       $this->comments[] = $comment;
       return $this;
    }
}
Using your entity
                                                      Create
                    <?php

                    class IndexController extends Zend_Controller_Action
                    {

                        public function init()
                        {
                            /* Initialize action controller here */
                        }

                        public function indexAction()
                        {
                            $documentManager = $this->getInvokeArg('bootstrap')->getResource('odm');
                            $post = new ApplicationBlogPost();
                            $post->setTitle('My Interesting Post')
                                 ->setContent('I have somethnng very interesting to say');
                            $documentManager->persist($post);
                            $documentManager->flush();
                        }


                    }

> use blog
switched to db blog
> db.posts.find();
{ "_id" : ObjectId("4dde4067fbd2237df1000000"), "title" : "My Interesting Post", "content" : "I have somethnng very
interesting to say" }
Using your entity
                                                     Update
                <?php

                class IndexController extends Zend_Controller_Action
                {

                    public function init()
                    {
                        /* Initialize action controller here */
                    }

                    public function indexAction()
                    {
                        $documentManager = $this->getInvokeArg('bootstrap')->getResource('odm');
                        $post = $documentManager->getRepository('ApplicationBlogPost')
                                                ->find('4dde4067fbd2237df1000000');
                        $post->setTitle('My Interesting Post')
                             ->setContent('I have something very interesting to say');
                        $documentManager->persist($post);
                        $documentManager->flush();
                    }


                }

> db.posts.find();
{ "_id" : ObjectId("4dde4067fbd2237df1000000"), "title" : "My Interesting Post", "content" : "I have something very
interesting to say" }
Using your entity
                                           Add an comment
                <?php

                class IndexController extends Zend_Controller_Action
                {

                    public function init()
                    {
                        /* Initialize action controller here */
                    }

                    public function indexAction()
                    {
                        $documentManager = $this->getInvokeArg('bootstrap')->getResource('odm');
                        $post = $documentManager->getRepository('ApplicationBlogPost')
                                                ->find('4dde4067fbd2237df1000000');
                        $comment = new ApplicationBlogComment();
                        $comment->setEmail('foo@example.com')
                                ->setComment('Nice post!');
                        $post->addComment($comment);
                        $documentManager->persist($post);
                        $documentManager->flush();
                    }

                }
> db.posts.find();
{ "_id" : ObjectId("4dde4067fbd2237df1000000"), "comments" : [
    {
         "_id" : ObjectId("4dde439afbd22380f1000000"),
         "email" : "foo@example.com",
         "comment" : "Nice post!"
    }
], "content" : "I have something very interesting to say", "title" : "My Interesting Post" }
Using your entity
                                                     Delete
            <?php

            class IndexController extends Zend_Controller_Action
            {

                public function init()
                {
                    /* Initialize action controller here */
                }

                public function indexAction()
                {
                    $documentManager = $this->getInvokeArg('bootstrap')->getResource('odm');
                    $post = $documentManager->getRepository('ApplicationBlogPost')
                                            ->find('4dde4067fbd2237df1000000');
                    $documentManager->remove($post);
                    $documentManager->flush();
                }


            }




> db.posts.find();
>
Available Annotations
http://www.doctrine-project.org/docs/mongodb_odm/1.0/en/
           reference/annotations-reference.html
Available Annotations
http://www.doctrine-project.org/docs/mongodb_odm/1.0/en/
           reference/annotations-reference.html
 @Field(type="string" name="origin")

    Field Mappings. Many aliases are available: @String, @Date, @Int, @Float etc.

 @EmbedOne / @EmbedMany

    Embedded Documents, stores the document inside the current document

 @ReferenceOne / @ReferenceMany

    Referenced Documents, stores a reference to one or more documents outside the current document

 @Document / @EmbeddedDocument

    Marks entities which are allowed to be managed by the document manager. additionally
    EmbeddedDocuments may not be saved independently, and must be a child of an @Document

 @HasLifecycleCallbacks & @PrePersist, @PostPersist etc.

   Marks an entity as having callbacks such as PrePersist which will be called automatically by the
   DocumentManager during the entities lifetime. (see reference for list)
Integrating with ZF
Integrating with ZF
Example Sandbox: http://github.com/bittarman/zf-d2-odm
           Includes all (PHP) dependencies
               Requires the mongo pecl extension
      $ sudo pecl install mongo




                     Install Doctrine from PEAR
     $ sudo pear channel-discover pear.doctrine-project.org
     $ sudo pear install pear.doctrine-project.org/DoctrineMongoDBODM-1.0.0BETA3



                            Checkout from Github
             $ git clone git://github.com/doctrine/mongodb-odm.git mongodb_odm
             $ cd mongodb_odm
             $ git checkout 1.0.0BETA3
The Plugin Resource
<?php

/* Import namespaces */
use DoctrineCommonClassLoader,
    DoctrineCommonAnnotationsAnnotationReader,
    DoctrineODMMongoDB,
    DoctrineODMMongoDBDocumentManager,
    DoctrineODMMongoDBMongo,
    DoctrineODMMongoDBMappingDriverAnnotationDriver;

/**
  * Doctrine 2 ODM Resource Plugin
  *
  * @author Ryan Mauger
  * @copyright Ryan Mauger 2012
  */
class Lupi_Resource_Odm extends Zend_Application_Resource_ResourceAbstract
{
     public function init()
     {
       $options = $this->getOptions();
       $this->registerAutoloaders($options);

        // Config
        $config = new DoctrineODMMongoDBConfiguration();
        foreach ($options['config'] as $option => $value) {
            $method = "set" . ucfirst($option);
            $config->{$method}($value);
        }

        // Annotation reader
        $reader = new AnnotationReader();
        $reader->setDefaultAnnotationNamespace('DoctrineODMMongoDBMapping');
        $config->setMetadataDriverImpl(new AnnotationDriver($reader, $options['documents']['dir']));

        $dm = DocumentManager::create(new DoctrineMongoDBConnection(new Mongo), $config);
        return $dm;
    }

    public function registerAutoloaders($options)
    {
        $autoloader = Zend_Loader_Autoloader::getInstance();

        // Document classes
        $classLoader = new ClassLoader($options['documents']['namespace'],
                                       $options['documents']['dir']);
        $autoloader->pushAutoloader(array($classLoader, 'loadClass'), $options['documents']['namespace']);

    }
}
The Plugin Resource
<?php

/* Import namespaces */
use DoctrineCommonClassLoader,
    DoctrineCommonAnnotationsAnnotationReader,
    DoctrineODMMongoDB,
    DoctrineODMMongoDBDocumentManager,
    DoctrineODMMongoDBMongo,
    DoctrineODMMongoDBMappingDriverAnnotationDriver;

/**
  * Doctrine 2 ODM Resource Plugin
  *
  * @author Ryan Mauger
  * @copyright Ryan Mauger 2012
  */
class Lupi_Resource_Odm extends Zend_Application_Resource_ResourceAbstract
{
     public function init()
     {
       $options = $this->getOptions();
       $this->registerAutoloaders($options);                                          Set up class loaders.
        // Config
        $config = new DoctrineODMMongoDBConfiguration();
        foreach ($options['config'] as $option => $value) {
            $method = "set" . ucfirst($option);
                                                                                       Use the Doctrine
            $config->{$method}($value);
        }

        // Annotation reader
                                                                                        loaders for ease
        $reader = new AnnotationReader();
        $reader->setDefaultAnnotationNamespace('DoctrineODMMongoDBMapping');
        $config->setMetadataDriverImpl(new AnnotationDriver($reader, $options['documents']['dir']));

        $dm = DocumentManager::create(new DoctrineMongoDBConnection(new Mongo), $config);
        return $dm;
    }

    public function registerAutoloaders($options)
    {
        $autoloader = Zend_Loader_Autoloader::getInstance();

        // Document classes
        $classLoader = new ClassLoader($options['documents']['namespace'],
                                       $options['documents']['dir']);
        $autoloader->pushAutoloader(array($classLoader, 'loadClass'), $options['documents']['namespace']);

    }
}
The Plugin Resource
<?php

/* Import namespaces */
use DoctrineCommonClassLoader,
    DoctrineCommonAnnotationsAnnotationReader,
    DoctrineODMMongoDB,
    DoctrineODMMongoDBDocumentManager,
    DoctrineODMMongoDBMongo,
    DoctrineODMMongoDBMappingDriverAnnotationDriver;

/**
  * Doctrine 2 ODM Resource Plugin
  *
  * @author Ryan Mauger
  * @copyright Ryan Mauger 2012
  */
class Lupi_Resource_Odm extends Zend_Application_Resource_ResourceAbstract
{
     public function init()
     {
       $options = $this->getOptions();
       $this->registerAutoloaders($options);

        // Config
        $config = new DoctrineODMMongoDBConfiguration();
        foreach ($options['config'] as $option => $value) {
                                                                                     Set up the conļ¬g object
            $method = "set" . ucfirst($option);
            $config->{$method}($value);
        }

        // Annotation reader
        $reader = new AnnotationReader();
        $reader->setDefaultAnnotationNamespace('DoctrineODMMongoDBMapping');
        $config->setMetadataDriverImpl(new AnnotationDriver($reader, $options['documents']['dir']));

        $dm = DocumentManager::create(new DoctrineMongoDBConnection(new Mongo), $config);
        return $dm;
    }

    public function registerAutoloaders($options)
    {
        $autoloader = Zend_Loader_Autoloader::getInstance();

        // Document classes
        $classLoader = new ClassLoader($options['documents']['namespace'],
                                       $options['documents']['dir']);
        $autoloader->pushAutoloader(array($classLoader, 'loadClass'), $options['documents']['namespace']);

    }
}
The Plugin Resource
<?php

/* Import namespaces */
use DoctrineCommonClassLoader,
    DoctrineCommonAnnotationsAnnotationReader,
    DoctrineODMMongoDB,
    DoctrineODMMongoDBDocumentManager,
    DoctrineODMMongoDBMongo,
    DoctrineODMMongoDBMappingDriverAnnotationDriver;

/**
  * Doctrine 2 ODM Resource Plugin
  *
  * @author Ryan Mauger
  * @copyright Ryan Mauger 2012
  */
class Lupi_Resource_Odm extends Zend_Application_Resource_ResourceAbstract
{
     public function init()
     {
                                                                                    Set up the Annotation
       $options = $this->getOptions();
       $this->registerAutoloaders($options);

        // Config
                                                                                  Reader, or mapping driver
        $config = new DoctrineODMMongoDBConfiguration();
        foreach ($options['config'] as $option => $value) {
            $method = "set" . ucfirst($option);
            $config->{$method}($value);
                                                                                  should you prefer YAML /
        }

        // Annotation reader
                                                                                            XML
        $reader = new AnnotationReader();
        $reader->setDefaultAnnotationNamespace('DoctrineODMMongoDBMapping');
        $config->setMetadataDriverImpl(new AnnotationDriver($reader, $options['documents']['dir']));

        $dm = DocumentManager::create(new DoctrineMongoDBConnection(new Mongo), $config);
        return $dm;
    }

    public function registerAutoloaders($options)
    {
        $autoloader = Zend_Loader_Autoloader::getInstance();

        // Document classes
        $classLoader = new ClassLoader($options['documents']['namespace'],
                                       $options['documents']['dir']);
        $autoloader->pushAutoloader(array($classLoader, 'loadClass'), $options['documents']['namespace']);

    }
}
The Plugin Resource
<?php

/* Import namespaces */
use DoctrineCommonClassLoader,
    DoctrineCommonAnnotationsAnnotationReader,
    DoctrineODMMongoDB,
    DoctrineODMMongoDBDocumentManager,
    DoctrineODMMongoDBMongo,
    DoctrineODMMongoDBMappingDriverAnnotationDriver;

/**
  * Doctrine 2 ODM Resource Plugin
  *
  * @author Ryan Mauger
  * @copyright Ryan Mauger 2012
  */
class Lupi_Resource_Odm extends Zend_Application_Resource_ResourceAbstract
{
     public function init()
     {
       $options = $this->getOptions();
       $this->registerAutoloaders($options);

        // Config
                                                                                        Create and return the
        $config = new DoctrineODMMongoDBConfiguration();
        foreach ($options['config'] as $option => $value) {
            $method = "set" . ucfirst($option);
            $config->{$method}($value);
                                                                                         Document manager
        }

        // Annotation reader
        $reader = new AnnotationReader();
        $reader->setDefaultAnnotationNamespace('DoctrineODMMongoDBMapping');
        $config->setMetadataDriverImpl(new AnnotationDriver($reader, $options['documents']['dir']));

        $dm = DocumentManager::create(new DoctrineMongoDBConnection(new Mongo), $config);
        return $dm;
    }

    public function registerAutoloaders($options)
    {
        $autoloader = Zend_Loader_Autoloader::getInstance();

        // Document classes
        $classLoader = new ClassLoader($options['documents']['namespace'],
                                       $options['documents']['dir']);
        $autoloader->pushAutoloader(array($classLoader, 'loadClass'), $options['documents']['namespace']);

    }
}
[production]
; PHP settings
phpSettings.display_startup_errors = 0
phpSettings.display_errors = 0

; Set Plugin path for lupi mongoodm resource
                                                                                  Conļ¬guration
pluginPaths.Lupi_Resource = APPLICATION_PATH "/../library/Lupi/Resource"

; Library include paths & namespaces
includePaths.library = APPLICATION_PATH "/../library"
autoloaderNamespaces[] = "Lupi"
autoloaderNamespaces[] = "Doctrine"

; Bootstrap options
bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
bootstrap.class = "Bootstrap"

; Applicaiton Setup
appnamespace = "Application"
resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
resources.frontController.params.displayExceptions = 0

; ODM settings
resources.odm.documents.dir = APPLICATION_PATH "/entities"
resources.odm.documents.namespace = "Application"
resources.odm.config.proxyDir = APPLICATION_PATH "/cache/proxies"
resources.odm.config.proxyNamespace = "proxies"
resources.odm.config.hydratorDir = APPLICATION_PATH "/cache/hydrators"
resources.odm.config.hydratorNamespace = "hydrators"



[staging : production]

[testing : production]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1

[development : production]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1
resources.frontController.params.displayExceptions = 1
[production]
; PHP settings
phpSettings.display_startup_errors = 0
phpSettings.display_errors = 0

; Set Plugin path for lupi mongoodm resource
                                                                                  Conļ¬guration
pluginPaths.Lupi_Resource = APPLICATION_PATH "/../library/Lupi/Resource"

; Library include paths & namespaces
includePaths.library = APPLICATION_PATH "/../library"
autoloaderNamespaces[] = "Lupi"
autoloaderNamespaces[] = "Doctrine"

; Bootstrap options
                                                        Tell it where to load the plugin resource
bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
bootstrap.class = "Bootstrap"

; Applicaiton Setup
appnamespace = "Application"
resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
resources.frontController.params.displayExceptions = 0

; ODM settings
resources.odm.documents.dir = APPLICATION_PATH "/entities"
resources.odm.documents.namespace = "Application"
resources.odm.config.proxyDir = APPLICATION_PATH "/cache/proxies"
resources.odm.config.proxyNamespace = "proxies"
resources.odm.config.hydratorDir = APPLICATION_PATH "/cache/hydrators"
resources.odm.config.hydratorNamespace = "hydrators"



[staging : production]

[testing : production]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1

[development : production]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1
resources.frontController.params.displayExceptions = 1
[production]
; PHP settings
phpSettings.display_startup_errors = 0
phpSettings.display_errors = 0

; Set Plugin path for lupi mongoodm resource
                                                                                  Conļ¬guration
pluginPaths.Lupi_Resource = APPLICATION_PATH "/../library/Lupi/Resource"

; Library include paths & namespaces
includePaths.library = APPLICATION_PATH "/../library"
autoloaderNamespaces[] = "Lupi"
autoloaderNamespaces[] = "Doctrine"

; Bootstrap options
                                                                  Minimal conļ¬g to get started
bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
bootstrap.class = "Bootstrap"

; Applicaiton Setup
appnamespace = "Application"
resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
resources.frontController.params.displayExceptions = 0

; ODM settings
resources.odm.documents.dir = APPLICATION_PATH "/entities"
resources.odm.documents.namespace = "Application"
resources.odm.config.proxyDir = APPLICATION_PATH "/cache/proxies"
resources.odm.config.proxyNamespace = "proxies"
resources.odm.config.hydratorDir = APPLICATION_PATH "/cache/hydrators"
resources.odm.config.hydratorNamespace = "hydrators"



[staging : production]

[testing : production]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1

[development : production]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1
resources.frontController.params.displayExceptions = 1
Base Controller

ā€¢ Provide an easy method to access the
 DocumentManager, and perhaps a service
 layer / repository

ā€¢ Not using an action helper because we will be
 likely to be using this tightly everywhere, so it
 avoids writing _helper a few hundred times!

ā€¢ You could use an action helper and use IOC or
 similar to replace this, this is for simplicity
<?php
namespace LupiController;
                                                               Base Controller
abstract class Action extends Zend_Controller_Action
{
    /**
     * @var Zend_Application
     */                                    Override the constructor at this point!
    protected $bootstrap;

    /**
     * @var DoctrineODMMongoDBDocumentManager
     */
    protected $dm;
                                                                                  Itā€™s useful to leave
    public function __construct(Zend_Controller_Request_Abstract $request,
                                Zend_Controller_Response_Abstract $response,
                                array $invokeArgs = array())
                                                                                  init() for the ļ¬nal
    {
        $this->setRequest($request)
             ->setResponse($response)
                                                                                 implementation so
             ->_setInvokeArgs($invokeArgs);
        $this->_helper = new Zend_Controller_Action_HelperBroker($this);
        $this->dm = $this->getBootstrap()->getResource('odm');
                                                                                  you donā€™t need to
        $this->init();
    }                                                                           remember to always
    public function getBootstrap()
    {
        if (null === $this->bootstrap) {
                                                                                   call parent::init()
            $this->bootstrap = $this->getInvokeArg('bootstrap');
        }
        return $this->bootstrap;
    }
}
Simpliļ¬ed controller code
<?php
use LupiController as controller;

class IndexController extends controllerAction
{
                                                                       Common repository for
    /**
     * @var DoctrineODMMongoDBDocumentRepository
     */
                                                                       the controller, set it in
    protected $repository;

    public function init()
                                                                              the init
    {
        $this->repository = $this->dm->getRepository('ApplicationBlogPost');
    }

    public function indexAction()
    {
        $post = $this->repository->find('4dde4067fbd2237df1000000');
        $comment = new ApplicationBlogComment();
        $comment->setEmail('foo@test.com')
                ->setComment('nice post!');
        $post->addComment($comment);
        $this->dm->persist($post);
        $this->dm->flush();
    }


}
Simpliļ¬ed controller code
<?php
use LupiController as controller;

class IndexController extends controllerAction
{
                                                                       Common repository for
    /**
     * @var DoctrineODMMongoDBDocumentRepository
     */
                                                                       the controller, set it in
    protected $repository;

    public function init()
                                                                              the init
    {
        $this->repository = $this->dm->getRepository('ApplicationBlogPost');
    }

    public function indexAction()
    {
        $post = $this->repository->find('4dde4067fbd2237df1000000');
        $comment = new ApplicationBlogComment();
        $comment->setEmail('foo@test.com')
                ->setComment('nice post!');
        $post->addComment($comment);
        $this->dm->persist($post);
        $this->dm->flush();
    }


}




                              Nice verbose code!
Managing change
Managing change



ā€¢ For adding a new property, mostly, you donā€™t
 need to do much
Managing change




ā€¢ The db is schema-less
Managing change



ā€¢ The db is schema-less
ā€¢ You can add properties, without needing to
 update the old objects until your ready
Managing change


ā€¢ The db is schema-less
ā€¢ You can add properties, without needing to
 update the old objects until your ready

ā€¢ Simply add the property, and update old
 objects through your usual admin interface
Managing change

ā€¢ The db is schema-less
ā€¢ You can add properties, without needing to
 update the old objects until your ready

ā€¢ Simply add the property, and update old
 objects through your usual admin interface

ā€¢ Objects without the new property will simply
 have a null value until you change them
Managing change



Make use of the annotations!
Changing a property name
               From                                            To
<?php                                          <?php
namespace ApplicationBlog;                    namespace ApplicationBlog;

/**                                            /**
  * @Document(db="blog", collection="posts")     * @Document(db="blog", collection="posts")
  */                                             */
class Post                                     class Post
{                                              {
	     /**                                      	     /**
      * @Id                                          * @Id
	      */                                      	      */
	     private $id;                             	     private $id;
	                                              	
	     /**                                      	     /**
	      * @Field(type="string")                 	      * @Field(type="string")
	      */                                      	      */
	     private $name;                           	     private $title;
	                                              	
	     /**                                      	     /**
      * @String                                      * @String
      */                                             */
     private $content;                              private $content;
}                                              }
Changing a property name
               From                                                            To
                                                               <?php
<?php
                                                               namespace ApplicationBlog;
namespace ApplicationBlog;

                                                               /**
/**
                                                                 * @Document(db="blog", collection="posts")
  * @Document(db="blog", collection="posts")
                                                                 */
  */
                                                               class Post
class Post
                                                               {
{
	     /**
      * @Id
                                               Add @AlsoLoad   	

                                                               	
                                                                     /**
                                                                     * @Id
                                                                      */
	      */
                                                               	     private $id;
	     private $id;
                                                               	
	
                                                               	     /**
	     /**
                                                               	      * @Field(type="string")
	      * @Field(type="string")
                                                               	      * @AlsoLoad({ā€œnameā€})
	      */
                                                               	      */
	     private $name;
                                                               	     private $title;
	
                                                               	
	     /**
                                                               	     /**
      * @String
                                                                     * @String
      */
                                                                     */
     private $content;
                                                                    private $content;
}
                                                               }
Transforming a property
               From                                                                           To
                                                                <?php
                                                                namespace ApplicationBlog;

<?php
                                                                /**
namespace ApplicationBlog;
                                                                  * @Document(db="blog", collection="posts")
                                                                  */
/**
                                                                class User
  * @Document(db="blog", collection="posts")
                                                                {
  */
                                                                	      /**
class User
                                                                       * @Id
{
                                                                	        */
	     /**
                                                                	      private $id;
      * @Id
                                                                	
	      */
                                                                     /**
	     private $id;
                                                                       * @Field(type="string")
	
                                                                       */
	     /**
                                                                      private $firstname;
	      * @Field(type="string")
	      */
                                                                    /**
	     private $fullname;
                                                                      * @Field(type="string")
                                                                      */
	    /**
                                                                     private $lastname;
     * @ReferenceMany(targetDocument=ā€ApplicationBlogPostā€)
     */
                                                                	     /**
    private $posts;
                                                                      * @ReferenceMany(targetDocument=ā€ApplicationBlogPostā€)
}
                                                                      */
                                                                     private $posts;
                                                                }
Transforming a property
               From                                             <?php
                                                                                              To
                                                                namespace ApplicationBlog;

                                                                /**
                                                                  * @Document(db="blog", collection="posts")
<?php                                                             */
namespace ApplicationBlog;                                     class User
                                                                {
/**                                                                  /**
                                                                      * @Id
  * @Document(db="blog", collection="posts")                          */
  */                                                                 private $id;
class User
{                                                                    /**
                                                                      * @Field(type="string")
	     /**                                                             */
      * @Id                                                          private $firstname;
	      */
	     private $id;                                                  /**
                                                                      * @Field(type="string")
	                                                                     */
	     /**                                                            private $lastname;
	      * @Field(type="string")
	      */                                                            /**
                                                                      * @ReferenceMany(targetDocument=ā€ApplicationBlogPostā€)
	     private $fulllname;                                             */
                                                                     private $posts;
	    /**
     * @ReferenceMany(targetDocument=ā€ApplicationBlogPostā€)       /**
                                                                      * @AlsoLoad({ā€œfullnameā€})
     */                                                               */
    private $posts;                                                 public function populateNameProperties($fullname)
}                                                                   {
                                                                         $name = explode(ā€˜ ā€˜, $fullname);
                                                                         $this->firstname = $name[0];
                                                                         $this->lastname = $name[1];
    Use a method to migrate using                               }
                                                                    }



             @AlsoLoad
NOTE!


ā€¢ When searching, your queries will not know
 about the old name!

ā€¢ Include old and new ļ¬elds in your searches if
 possible until all data has been migrated
NOTE!


ā€¢ The ODM is still in BETA3, there are still
 some glitches, but its well worth having a good
 look now.

ā€¢ http://www.doctrine-project.org/ and follow
 progress
Useful information

ā€¢ Oļ¬ƒcial docs: http://www.doctrine-project.org/
 docs/mongodb_odm/1.0/en/

ā€¢ Mongodb: http://www.mongodb.org/ excellent
 intro to mongodb

ā€¢ The example sandbox: http://github.com/
 bittarman/zf-d2-odm
Thanks for listening
 Catch me on twitter: @Bittarman
      Slides will be available on slideshare
         http://slideshare.com/rmauger



ZF & Doctrine 2 ODM


                                               Doctrine

More Related Content

What's hot

Symfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il clienteSymfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il clienteLeonardo Proietti
Ā 
Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5Leonardo Proietti
Ā 
Adding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy ApplicationsAdding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy ApplicationsSam Hennessy
Ā 
A resource oriented framework using the DI/AOP/REST triangle
A resource oriented framework using the DI/AOP/REST triangleA resource oriented framework using the DI/AOP/REST triangle
A resource oriented framework using the DI/AOP/REST triangleAkihito Koriyama
Ā 
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you need
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you needDutch PHP Conference - PHPSpec 2 - The only Design Tool you need
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you needKacper Gunia
Ā 
Š”ŠøстŠµŠ¼Š° рŠµŠ½Š“ŠµŃ€ŠøŠ½Š³Š° Š² Magento
Š”ŠøстŠµŠ¼Š° рŠµŠ½Š“ŠµŃ€ŠøŠ½Š³Š° Š² MagentoŠ”ŠøстŠµŠ¼Š° рŠµŠ½Š“ŠµŃ€ŠøŠ½Š³Š° Š² Magento
Š”ŠøстŠµŠ¼Š° рŠµŠ½Š“ŠµŃ€ŠøŠ½Š³Š° Š² MagentoMagecom Ukraine
Ā 
Durian: a PHP 5.5 microframework with generator-style middleware
Durian: a PHP 5.5 microframework with generator-style middlewareDurian: a PHP 5.5 microframework with generator-style middleware
Durian: a PHP 5.5 microframework with generator-style middlewareKuan Yen Heng
Ā 
Design how your objects talk through mocking
Design how your objects talk through mockingDesign how your objects talk through mocking
Design how your objects talk through mockingKonstantin Kudryashov
Ā 
Introduction to DI(C)
Introduction to DI(C)Introduction to DI(C)
Introduction to DI(C)Radek Benkel
Ā 
Be pragmatic, be SOLID (at Boiling Frogs, Wrocław)
Be pragmatic, be SOLID (at Boiling Frogs, Wrocław)Be pragmatic, be SOLID (at Boiling Frogs, Wrocław)
Be pragmatic, be SOLID (at Boiling Frogs, Wrocław)Krzysztof Menżyk
Ā 
Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
 Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011 Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011Alessandro Nadalin
Ā 
Symfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technologySymfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technologyDaniel Knell
Ā 
Intro programacion funcional
Intro programacion funcionalIntro programacion funcional
Intro programacion funcionalNSCoder Mexico
Ā 
Solid principles
Solid principlesSolid principles
Solid principlesDeclan Whelan
Ā 
Crafting beautiful software
Crafting beautiful softwareCrafting beautiful software
Crafting beautiful softwareJorn Oomen
Ā 
Field api.From d7 to d8
Field api.From d7 to d8Field api.From d7 to d8
Field api.From d7 to d8Pavel Makhrinsky
Ā 
Drupal Field API. Practical usage
Drupal Field API. Practical usageDrupal Field API. Practical usage
Drupal Field API. Practical usagePavel Makhrinsky
Ā 

What's hot (20)

Symfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il clienteSymfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il cliente
Ā 
Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5
Ā 
Adding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy ApplicationsAdding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy Applications
Ā 
A resource oriented framework using the DI/AOP/REST triangle
A resource oriented framework using the DI/AOP/REST triangleA resource oriented framework using the DI/AOP/REST triangle
A resource oriented framework using the DI/AOP/REST triangle
Ā 
SOLID PRINCIPLES
SOLID PRINCIPLESSOLID PRINCIPLES
SOLID PRINCIPLES
Ā 
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you need
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you needDutch PHP Conference - PHPSpec 2 - The only Design Tool you need
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you need
Ā 
Taming Command Bus
Taming Command BusTaming Command Bus
Taming Command Bus
Ā 
Oops in php
Oops in phpOops in php
Oops in php
Ā 
Š”ŠøстŠµŠ¼Š° рŠµŠ½Š“ŠµŃ€ŠøŠ½Š³Š° Š² Magento
Š”ŠøстŠµŠ¼Š° рŠµŠ½Š“ŠµŃ€ŠøŠ½Š³Š° Š² MagentoŠ”ŠøстŠµŠ¼Š° рŠµŠ½Š“ŠµŃ€ŠøŠ½Š³Š° Š² Magento
Š”ŠøстŠµŠ¼Š° рŠµŠ½Š“ŠµŃ€ŠøŠ½Š³Š° Š² Magento
Ā 
Durian: a PHP 5.5 microframework with generator-style middleware
Durian: a PHP 5.5 microframework with generator-style middlewareDurian: a PHP 5.5 microframework with generator-style middleware
Durian: a PHP 5.5 microframework with generator-style middleware
Ā 
Design how your objects talk through mocking
Design how your objects talk through mockingDesign how your objects talk through mocking
Design how your objects talk through mocking
Ā 
Introduction to DI(C)
Introduction to DI(C)Introduction to DI(C)
Introduction to DI(C)
Ā 
Be pragmatic, be SOLID (at Boiling Frogs, Wrocław)
Be pragmatic, be SOLID (at Boiling Frogs, Wrocław)Be pragmatic, be SOLID (at Boiling Frogs, Wrocław)
Be pragmatic, be SOLID (at Boiling Frogs, Wrocław)
Ā 
Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
 Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011 Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
Ā 
Symfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technologySymfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technology
Ā 
Intro programacion funcional
Intro programacion funcionalIntro programacion funcional
Intro programacion funcional
Ā 
Solid principles
Solid principlesSolid principles
Solid principles
Ā 
Crafting beautiful software
Crafting beautiful softwareCrafting beautiful software
Crafting beautiful software
Ā 
Field api.From d7 to d8
Field api.From d7 to d8Field api.From d7 to d8
Field api.From d7 to d8
Ā 
Drupal Field API. Practical usage
Drupal Field API. Practical usageDrupal Field API. Practical usage
Drupal Field API. Practical usage
Ā 

Similar to Zend Framework and the Doctrine2 MongoDB ODM (ZF1)

How Kris Writes Symfony Apps
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony AppsKris Wallsmith
Ā 
Migrare da symfony 1 a Symfony2
 Migrare da symfony 1 a Symfony2  Migrare da symfony 1 a Symfony2
Migrare da symfony 1 a Symfony2 Massimiliano Arione
Ā 
Migrating to dependency injection
Migrating to dependency injectionMigrating to dependency injection
Migrating to dependency injectionJosh Adell
Ā 
Introducing CakeEntity
Introducing CakeEntityIntroducing CakeEntity
Introducing CakeEntityBasuke Suzuki
Ā 
Php on the desktop and php gtk2
Php on the desktop and php gtk2Php on the desktop and php gtk2
Php on the desktop and php gtk2Elizabeth Smith
Ā 
Doctrine MongoDB Object Document Mapper
Doctrine MongoDB Object Document MapperDoctrine MongoDB Object Document Mapper
Doctrine MongoDB Object Document MapperJonathan Wage
Ā 
Drupal 8 Services And Dependency Injection
Drupal 8 Services And Dependency InjectionDrupal 8 Services And Dependency Injection
Drupal 8 Services And Dependency InjectionPhilip Norton
Ā 
Unittests fĆ¼r Dummies
Unittests fĆ¼r DummiesUnittests fĆ¼r Dummies
Unittests fĆ¼r DummiesLars Jankowfsky
Ā 
ZG PHP - Specification
ZG PHP - SpecificationZG PHP - Specification
ZG PHP - SpecificationRobert Å orn
Ā 
SPL: The Missing Link in Development
SPL: The Missing Link in DevelopmentSPL: The Missing Link in Development
SPL: The Missing Link in Developmentjsmith92
Ā 
Advanced php testing in action
Advanced php testing in actionAdvanced php testing in action
Advanced php testing in actionJace Ju
Ā 
4Developers 2015: Be pragmatic, be SOLID - Krzysztof Menżyk
4Developers 2015: Be pragmatic, be SOLID - Krzysztof Menżyk4Developers 2015: Be pragmatic, be SOLID - Krzysztof Menżyk
4Developers 2015: Be pragmatic, be SOLID - Krzysztof MenżykPROIDEA
Ā 
ŠšŠ°Šŗ ŠæŠ¾Š»ŃƒŃ‡Šøть чёрŠ½Ń‹Š¹ ŠæŠ¾ŃŃ ŠæŠ¾ WordPress? v2.0
ŠšŠ°Šŗ ŠæŠ¾Š»ŃƒŃ‡Šøть чёрŠ½Ń‹Š¹ ŠæŠ¾ŃŃ ŠæŠ¾ WordPress? v2.0ŠšŠ°Šŗ ŠæŠ¾Š»ŃƒŃ‡Šøть чёрŠ½Ń‹Š¹ ŠæŠ¾ŃŃ ŠæŠ¾ WordPress? v2.0
ŠšŠ°Šŗ ŠæŠ¾Š»ŃƒŃ‡Šøть чёрŠ½Ń‹Š¹ ŠæŠ¾ŃŃ ŠæŠ¾ WordPress? v2.0Yevhen Kotelnytskyi
Ā 
ZF2 for the ZF1 Developer
ZF2 for the ZF1 DeveloperZF2 for the ZF1 Developer
ZF2 for the ZF1 DeveloperGary Hockin
Ā 
DrupalJam 2018 - Maintaining a Drupal Module: Keep It Small and Simple
DrupalJam 2018 - Maintaining a Drupal Module: Keep It Small and SimpleDrupalJam 2018 - Maintaining a Drupal Module: Keep It Small and Simple
DrupalJam 2018 - Maintaining a Drupal Module: Keep It Small and SimpleAlexander Varwijk
Ā 

Similar to Zend Framework and the Doctrine2 MongoDB ODM (ZF1) (20)

How Kris Writes Symfony Apps
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony Apps
Ā 
Migrare da symfony 1 a Symfony2
 Migrare da symfony 1 a Symfony2  Migrare da symfony 1 a Symfony2
Migrare da symfony 1 a Symfony2
Ā 
Doctrine for NoSQL
Doctrine for NoSQLDoctrine for NoSQL
Doctrine for NoSQL
Ā 
Doctrine and NoSQL
Doctrine and NoSQLDoctrine and NoSQL
Doctrine and NoSQL
Ā 
Migrating to dependency injection
Migrating to dependency injectionMigrating to dependency injection
Migrating to dependency injection
Ā 
Introducing CakeEntity
Introducing CakeEntityIntroducing CakeEntity
Introducing CakeEntity
Ā 
Php on the desktop and php gtk2
Php on the desktop and php gtk2Php on the desktop and php gtk2
Php on the desktop and php gtk2
Ā 
Doctrine MongoDB Object Document Mapper
Doctrine MongoDB Object Document MapperDoctrine MongoDB Object Document Mapper
Doctrine MongoDB Object Document Mapper
Ā 
Drupal 8 Services And Dependency Injection
Drupal 8 Services And Dependency InjectionDrupal 8 Services And Dependency Injection
Drupal 8 Services And Dependency Injection
Ā 
Unittests fĆ¼r Dummies
Unittests fĆ¼r DummiesUnittests fĆ¼r Dummies
Unittests fĆ¼r Dummies
Ā 
ZG PHP - Specification
ZG PHP - SpecificationZG PHP - Specification
ZG PHP - Specification
Ā 
SPL: The Missing Link in Development
SPL: The Missing Link in DevelopmentSPL: The Missing Link in Development
SPL: The Missing Link in Development
Ā 
Jsp presentation
Jsp presentationJsp presentation
Jsp presentation
Ā 
Advanced php testing in action
Advanced php testing in actionAdvanced php testing in action
Advanced php testing in action
Ā 
4Developers 2015: Be pragmatic, be SOLID - Krzysztof Menżyk
4Developers 2015: Be pragmatic, be SOLID - Krzysztof Menżyk4Developers 2015: Be pragmatic, be SOLID - Krzysztof Menżyk
4Developers 2015: Be pragmatic, be SOLID - Krzysztof Menżyk
Ā 
Be pragmatic, be SOLID
Be pragmatic, be SOLIDBe pragmatic, be SOLID
Be pragmatic, be SOLID
Ā 
ŠšŠ°Šŗ ŠæŠ¾Š»ŃƒŃ‡Šøть чёрŠ½Ń‹Š¹ ŠæŠ¾ŃŃ ŠæŠ¾ WordPress? v2.0
ŠšŠ°Šŗ ŠæŠ¾Š»ŃƒŃ‡Šøть чёрŠ½Ń‹Š¹ ŠæŠ¾ŃŃ ŠæŠ¾ WordPress? v2.0ŠšŠ°Šŗ ŠæŠ¾Š»ŃƒŃ‡Šøть чёрŠ½Ń‹Š¹ ŠæŠ¾ŃŃ ŠæŠ¾ WordPress? v2.0
ŠšŠ°Šŗ ŠæŠ¾Š»ŃƒŃ‡Šøть чёрŠ½Ń‹Š¹ ŠæŠ¾ŃŃ ŠæŠ¾ WordPress? v2.0
Ā 
ZF2 for the ZF1 Developer
ZF2 for the ZF1 DeveloperZF2 for the ZF1 Developer
ZF2 for the ZF1 Developer
Ā 
DrupalJam 2018 - Maintaining a Drupal Module: Keep It Small and Simple
DrupalJam 2018 - Maintaining a Drupal Module: Keep It Small and SimpleDrupalJam 2018 - Maintaining a Drupal Module: Keep It Small and Simple
DrupalJam 2018 - Maintaining a Drupal Module: Keep It Small and Simple
Ā 
PHP OOP
PHP OOPPHP OOP
PHP OOP
Ā 

Recently uploaded

Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
Ā 
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
Ā 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
Ā 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel AraĆŗjo
Ā 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
Ā 
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
Ā 
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
Ā 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024The Digital Insurer
Ā 
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
Ā 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
Ā 
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
Ā 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
Ā 
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
Ā 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
Ā 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
Ā 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
Ā 
šŸ¬ 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
Ā 
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
Ā 
WhatsApp 9892124323 āœ“Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 āœ“Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 āœ“Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 āœ“Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
Ā 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfEnterprise Knowledge
Ā 

Recently uploaded (20)

Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Ā 
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
Ā 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
Ā 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Ā 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
Ā 
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
Ā 
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
Ā 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
Ā 
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
Ā 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
Ā 
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
Ā 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
Ā 
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
Ā 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Ā 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
Ā 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
Ā 
šŸ¬ The future of MySQL is Postgres šŸ˜
šŸ¬  The future of MySQL is Postgres   šŸ˜šŸ¬  The future of MySQL is Postgres   šŸ˜
šŸ¬ The future of MySQL is Postgres šŸ˜
Ā 
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
Ā 
WhatsApp 9892124323 āœ“Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 āœ“Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 āœ“Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 āœ“Call Girls In Kalyan ( Mumbai ) secure service
Ā 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
Ā 

Zend Framework and the Doctrine2 MongoDB ODM (ZF1)

  • 1. ZF & Doctrine 2 ODM Doctrine
  • 2. WHO IS RYAN MAUGER? ā€¢ Zend Framework Contributor ā€¢ Zend Framework CR Team Member ā€¢ Co-Author of Zend Framework 2 in Action (With Rob Allen) ā€¢ Technical Editor for Zend Framework: A Beginners Guide ā€¢ Community Supporter ā€¢ Zend Certiļ¬ed PHP5 Engineer ā€¢ Lead Developer at Lupimedia and trainer at Lupijuice
  • 3. What is the ODM?
  • 4. What is the ODM? Object Document Mapper
  • 5. What is the ODM? Object Document Mapper Similar to an ORM
  • 6. What is the ODM? Object Document Mapper Similar to an ORM But works with a Document Database
  • 7. What is the ODM? Object Document Mapper Similar to an ORM But works with a Document Database
  • 8. Whats the advantage? ā€¢ Schema-less design (no complicated ALTER TABLE statements, just save your data! ā€¢ Works with JSON objects, familiar with what your already doing ā€¢ Simple!
  • 9. Whats the advantage? ā€¢ Schema-less design (no complicated ALTER TABLE statements, just save your data! ā€¢ Works with JSON objects, familiar with what your already doing ā€¢ Simple! (at least to get started)
  • 10. Whats the advantage? Doctrine 2 ā€¢ Uses the Data Mapper pattern ā€¢ Simpliļ¬es your domain, removes the persistence logic ā€¢ Entities are free to do their job ā€¢ Deļ¬nes a framework by which your domain model will work, improving consistency
  • 11. Getting started with the ODM Persistence operations revolve around the Document Manager Mapping of properties is carried out through annotations in your entities, or through xml/yaml mappings
  • 12. <?php namespace ApplicationBlog; /** * @Document(db="blog", collection="posts") */ class Post { /** * @Id */ private $id; An example entity /** * @Field(type="string") */ private $title; /** * @String */ Properties private $content; /** /** * @EmbedMany(targetDocument="ApplicationBlogComment") */ * @Id private $comments = array(); */ public function getId() private $id; { return $this->id; } /** public function setId($id) * @Field(type="string") { $this->id = (string) $id; */ return $this; private $title; } public function getTitle() { /** return $this->title; * @String } */ public function setTitle($title) private $content; { $this->title = (string) $title; } return $this; /** * @EmbedMany(targetDocument="ApplicationBlogComment") public function getContent() { */ return $this->content; private $comments = array(); } public function setContent($content) { $this->content = (string) $content; return $this; } public function getComments() { return $this->comments; } public function addComment(ApplicationBlogComment $comment) { $this->comments[] = $comment; return $this; } }
  • 13. <?php namespace ApplicationBlog; /** * @Document(db="blog", collection="posts") */ class Post { /** * @Id */ private $id; An example entity /** * @Field(type="string") */ private $title; /** * @String */ Methods private $content; /** * @EmbedMany(targetDocument="ApplicationBlogComment") public function getContent() */ { private $comments = array(); return $this->content; public function getId() } { return $this->id; } public function setContent($content) public function setId($id) { { $this->id = (string) $id; $this->content = (string) $content; return $this; return $this; } } public function getTitle() { return $this->title; public function getComments() } { public function setTitle($title) return $this->comments; { $this->title = (string) $title; } return $this; } public function addComment(ApplicationBlogComment $comment) public function getContent() { { return $this->content; $this->comments[] = $comment; } return $this; public function setContent($content) { } $this->content = (string) $content; return $this; } public function getComments() { return $this->comments; } public function addComment(ApplicationBlogComment $comment) { $this->comments[] = $comment; return $this; } }
  • 14. Using your entity Create <?php class IndexController extends Zend_Controller_Action { public function init() { /* Initialize action controller here */ } public function indexAction() { $documentManager = $this->getInvokeArg('bootstrap')->getResource('odm'); $post = new ApplicationBlogPost(); $post->setTitle('My Interesting Post') ->setContent('I have somethnng very interesting to say'); $documentManager->persist($post); $documentManager->flush(); } } > use blog switched to db blog > db.posts.find(); { "_id" : ObjectId("4dde4067fbd2237df1000000"), "title" : "My Interesting Post", "content" : "I have somethnng very interesting to say" }
  • 15. Using your entity Update <?php class IndexController extends Zend_Controller_Action { public function init() { /* Initialize action controller here */ } public function indexAction() { $documentManager = $this->getInvokeArg('bootstrap')->getResource('odm'); $post = $documentManager->getRepository('ApplicationBlogPost') ->find('4dde4067fbd2237df1000000'); $post->setTitle('My Interesting Post') ->setContent('I have something very interesting to say'); $documentManager->persist($post); $documentManager->flush(); } } > db.posts.find(); { "_id" : ObjectId("4dde4067fbd2237df1000000"), "title" : "My Interesting Post", "content" : "I have something very interesting to say" }
  • 16. Using your entity Add an comment <?php class IndexController extends Zend_Controller_Action { public function init() { /* Initialize action controller here */ } public function indexAction() { $documentManager = $this->getInvokeArg('bootstrap')->getResource('odm'); $post = $documentManager->getRepository('ApplicationBlogPost') ->find('4dde4067fbd2237df1000000'); $comment = new ApplicationBlogComment(); $comment->setEmail('foo@example.com') ->setComment('Nice post!'); $post->addComment($comment); $documentManager->persist($post); $documentManager->flush(); } } > db.posts.find(); { "_id" : ObjectId("4dde4067fbd2237df1000000"), "comments" : [ { "_id" : ObjectId("4dde439afbd22380f1000000"), "email" : "foo@example.com", "comment" : "Nice post!" } ], "content" : "I have something very interesting to say", "title" : "My Interesting Post" }
  • 17. Using your entity Delete <?php class IndexController extends Zend_Controller_Action { public function init() { /* Initialize action controller here */ } public function indexAction() { $documentManager = $this->getInvokeArg('bootstrap')->getResource('odm'); $post = $documentManager->getRepository('ApplicationBlogPost') ->find('4dde4067fbd2237df1000000'); $documentManager->remove($post); $documentManager->flush(); } } > db.posts.find(); >
  • 19. Available Annotations http://www.doctrine-project.org/docs/mongodb_odm/1.0/en/ reference/annotations-reference.html @Field(type="string" name="origin") Field Mappings. Many aliases are available: @String, @Date, @Int, @Float etc. @EmbedOne / @EmbedMany Embedded Documents, stores the document inside the current document @ReferenceOne / @ReferenceMany Referenced Documents, stores a reference to one or more documents outside the current document @Document / @EmbeddedDocument Marks entities which are allowed to be managed by the document manager. additionally EmbeddedDocuments may not be saved independently, and must be a child of an @Document @HasLifecycleCallbacks & @PrePersist, @PostPersist etc. Marks an entity as having callbacks such as PrePersist which will be called automatically by the DocumentManager during the entities lifetime. (see reference for list)
  • 21. Integrating with ZF Example Sandbox: http://github.com/bittarman/zf-d2-odm Includes all (PHP) dependencies Requires the mongo pecl extension $ sudo pecl install mongo Install Doctrine from PEAR $ sudo pear channel-discover pear.doctrine-project.org $ sudo pear install pear.doctrine-project.org/DoctrineMongoDBODM-1.0.0BETA3 Checkout from Github $ git clone git://github.com/doctrine/mongodb-odm.git mongodb_odm $ cd mongodb_odm $ git checkout 1.0.0BETA3
  • 22. The Plugin Resource <?php /* Import namespaces */ use DoctrineCommonClassLoader, DoctrineCommonAnnotationsAnnotationReader, DoctrineODMMongoDB, DoctrineODMMongoDBDocumentManager, DoctrineODMMongoDBMongo, DoctrineODMMongoDBMappingDriverAnnotationDriver; /** * Doctrine 2 ODM Resource Plugin * * @author Ryan Mauger * @copyright Ryan Mauger 2012 */ class Lupi_Resource_Odm extends Zend_Application_Resource_ResourceAbstract { public function init() { $options = $this->getOptions(); $this->registerAutoloaders($options); // Config $config = new DoctrineODMMongoDBConfiguration(); foreach ($options['config'] as $option => $value) { $method = "set" . ucfirst($option); $config->{$method}($value); } // Annotation reader $reader = new AnnotationReader(); $reader->setDefaultAnnotationNamespace('DoctrineODMMongoDBMapping'); $config->setMetadataDriverImpl(new AnnotationDriver($reader, $options['documents']['dir'])); $dm = DocumentManager::create(new DoctrineMongoDBConnection(new Mongo), $config); return $dm; } public function registerAutoloaders($options) { $autoloader = Zend_Loader_Autoloader::getInstance(); // Document classes $classLoader = new ClassLoader($options['documents']['namespace'], $options['documents']['dir']); $autoloader->pushAutoloader(array($classLoader, 'loadClass'), $options['documents']['namespace']); } }
  • 23. The Plugin Resource <?php /* Import namespaces */ use DoctrineCommonClassLoader, DoctrineCommonAnnotationsAnnotationReader, DoctrineODMMongoDB, DoctrineODMMongoDBDocumentManager, DoctrineODMMongoDBMongo, DoctrineODMMongoDBMappingDriverAnnotationDriver; /** * Doctrine 2 ODM Resource Plugin * * @author Ryan Mauger * @copyright Ryan Mauger 2012 */ class Lupi_Resource_Odm extends Zend_Application_Resource_ResourceAbstract { public function init() { $options = $this->getOptions(); $this->registerAutoloaders($options); Set up class loaders. // Config $config = new DoctrineODMMongoDBConfiguration(); foreach ($options['config'] as $option => $value) { $method = "set" . ucfirst($option); Use the Doctrine $config->{$method}($value); } // Annotation reader loaders for ease $reader = new AnnotationReader(); $reader->setDefaultAnnotationNamespace('DoctrineODMMongoDBMapping'); $config->setMetadataDriverImpl(new AnnotationDriver($reader, $options['documents']['dir'])); $dm = DocumentManager::create(new DoctrineMongoDBConnection(new Mongo), $config); return $dm; } public function registerAutoloaders($options) { $autoloader = Zend_Loader_Autoloader::getInstance(); // Document classes $classLoader = new ClassLoader($options['documents']['namespace'], $options['documents']['dir']); $autoloader->pushAutoloader(array($classLoader, 'loadClass'), $options['documents']['namespace']); } }
  • 24. The Plugin Resource <?php /* Import namespaces */ use DoctrineCommonClassLoader, DoctrineCommonAnnotationsAnnotationReader, DoctrineODMMongoDB, DoctrineODMMongoDBDocumentManager, DoctrineODMMongoDBMongo, DoctrineODMMongoDBMappingDriverAnnotationDriver; /** * Doctrine 2 ODM Resource Plugin * * @author Ryan Mauger * @copyright Ryan Mauger 2012 */ class Lupi_Resource_Odm extends Zend_Application_Resource_ResourceAbstract { public function init() { $options = $this->getOptions(); $this->registerAutoloaders($options); // Config $config = new DoctrineODMMongoDBConfiguration(); foreach ($options['config'] as $option => $value) { Set up the conļ¬g object $method = "set" . ucfirst($option); $config->{$method}($value); } // Annotation reader $reader = new AnnotationReader(); $reader->setDefaultAnnotationNamespace('DoctrineODMMongoDBMapping'); $config->setMetadataDriverImpl(new AnnotationDriver($reader, $options['documents']['dir'])); $dm = DocumentManager::create(new DoctrineMongoDBConnection(new Mongo), $config); return $dm; } public function registerAutoloaders($options) { $autoloader = Zend_Loader_Autoloader::getInstance(); // Document classes $classLoader = new ClassLoader($options['documents']['namespace'], $options['documents']['dir']); $autoloader->pushAutoloader(array($classLoader, 'loadClass'), $options['documents']['namespace']); } }
  • 25. The Plugin Resource <?php /* Import namespaces */ use DoctrineCommonClassLoader, DoctrineCommonAnnotationsAnnotationReader, DoctrineODMMongoDB, DoctrineODMMongoDBDocumentManager, DoctrineODMMongoDBMongo, DoctrineODMMongoDBMappingDriverAnnotationDriver; /** * Doctrine 2 ODM Resource Plugin * * @author Ryan Mauger * @copyright Ryan Mauger 2012 */ class Lupi_Resource_Odm extends Zend_Application_Resource_ResourceAbstract { public function init() { Set up the Annotation $options = $this->getOptions(); $this->registerAutoloaders($options); // Config Reader, or mapping driver $config = new DoctrineODMMongoDBConfiguration(); foreach ($options['config'] as $option => $value) { $method = "set" . ucfirst($option); $config->{$method}($value); should you prefer YAML / } // Annotation reader XML $reader = new AnnotationReader(); $reader->setDefaultAnnotationNamespace('DoctrineODMMongoDBMapping'); $config->setMetadataDriverImpl(new AnnotationDriver($reader, $options['documents']['dir'])); $dm = DocumentManager::create(new DoctrineMongoDBConnection(new Mongo), $config); return $dm; } public function registerAutoloaders($options) { $autoloader = Zend_Loader_Autoloader::getInstance(); // Document classes $classLoader = new ClassLoader($options['documents']['namespace'], $options['documents']['dir']); $autoloader->pushAutoloader(array($classLoader, 'loadClass'), $options['documents']['namespace']); } }
  • 26. The Plugin Resource <?php /* Import namespaces */ use DoctrineCommonClassLoader, DoctrineCommonAnnotationsAnnotationReader, DoctrineODMMongoDB, DoctrineODMMongoDBDocumentManager, DoctrineODMMongoDBMongo, DoctrineODMMongoDBMappingDriverAnnotationDriver; /** * Doctrine 2 ODM Resource Plugin * * @author Ryan Mauger * @copyright Ryan Mauger 2012 */ class Lupi_Resource_Odm extends Zend_Application_Resource_ResourceAbstract { public function init() { $options = $this->getOptions(); $this->registerAutoloaders($options); // Config Create and return the $config = new DoctrineODMMongoDBConfiguration(); foreach ($options['config'] as $option => $value) { $method = "set" . ucfirst($option); $config->{$method}($value); Document manager } // Annotation reader $reader = new AnnotationReader(); $reader->setDefaultAnnotationNamespace('DoctrineODMMongoDBMapping'); $config->setMetadataDriverImpl(new AnnotationDriver($reader, $options['documents']['dir'])); $dm = DocumentManager::create(new DoctrineMongoDBConnection(new Mongo), $config); return $dm; } public function registerAutoloaders($options) { $autoloader = Zend_Loader_Autoloader::getInstance(); // Document classes $classLoader = new ClassLoader($options['documents']['namespace'], $options['documents']['dir']); $autoloader->pushAutoloader(array($classLoader, 'loadClass'), $options['documents']['namespace']); } }
  • 27. [production] ; PHP settings phpSettings.display_startup_errors = 0 phpSettings.display_errors = 0 ; Set Plugin path for lupi mongoodm resource Conļ¬guration pluginPaths.Lupi_Resource = APPLICATION_PATH "/../library/Lupi/Resource" ; Library include paths & namespaces includePaths.library = APPLICATION_PATH "/../library" autoloaderNamespaces[] = "Lupi" autoloaderNamespaces[] = "Doctrine" ; Bootstrap options bootstrap.path = APPLICATION_PATH "/Bootstrap.php" bootstrap.class = "Bootstrap" ; Applicaiton Setup appnamespace = "Application" resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers" resources.frontController.params.displayExceptions = 0 ; ODM settings resources.odm.documents.dir = APPLICATION_PATH "/entities" resources.odm.documents.namespace = "Application" resources.odm.config.proxyDir = APPLICATION_PATH "/cache/proxies" resources.odm.config.proxyNamespace = "proxies" resources.odm.config.hydratorDir = APPLICATION_PATH "/cache/hydrators" resources.odm.config.hydratorNamespace = "hydrators" [staging : production] [testing : production] phpSettings.display_startup_errors = 1 phpSettings.display_errors = 1 [development : production] phpSettings.display_startup_errors = 1 phpSettings.display_errors = 1 resources.frontController.params.displayExceptions = 1
  • 28. [production] ; PHP settings phpSettings.display_startup_errors = 0 phpSettings.display_errors = 0 ; Set Plugin path for lupi mongoodm resource Conļ¬guration pluginPaths.Lupi_Resource = APPLICATION_PATH "/../library/Lupi/Resource" ; Library include paths & namespaces includePaths.library = APPLICATION_PATH "/../library" autoloaderNamespaces[] = "Lupi" autoloaderNamespaces[] = "Doctrine" ; Bootstrap options Tell it where to load the plugin resource bootstrap.path = APPLICATION_PATH "/Bootstrap.php" bootstrap.class = "Bootstrap" ; Applicaiton Setup appnamespace = "Application" resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers" resources.frontController.params.displayExceptions = 0 ; ODM settings resources.odm.documents.dir = APPLICATION_PATH "/entities" resources.odm.documents.namespace = "Application" resources.odm.config.proxyDir = APPLICATION_PATH "/cache/proxies" resources.odm.config.proxyNamespace = "proxies" resources.odm.config.hydratorDir = APPLICATION_PATH "/cache/hydrators" resources.odm.config.hydratorNamespace = "hydrators" [staging : production] [testing : production] phpSettings.display_startup_errors = 1 phpSettings.display_errors = 1 [development : production] phpSettings.display_startup_errors = 1 phpSettings.display_errors = 1 resources.frontController.params.displayExceptions = 1
  • 29. [production] ; PHP settings phpSettings.display_startup_errors = 0 phpSettings.display_errors = 0 ; Set Plugin path for lupi mongoodm resource Conļ¬guration pluginPaths.Lupi_Resource = APPLICATION_PATH "/../library/Lupi/Resource" ; Library include paths & namespaces includePaths.library = APPLICATION_PATH "/../library" autoloaderNamespaces[] = "Lupi" autoloaderNamespaces[] = "Doctrine" ; Bootstrap options Minimal conļ¬g to get started bootstrap.path = APPLICATION_PATH "/Bootstrap.php" bootstrap.class = "Bootstrap" ; Applicaiton Setup appnamespace = "Application" resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers" resources.frontController.params.displayExceptions = 0 ; ODM settings resources.odm.documents.dir = APPLICATION_PATH "/entities" resources.odm.documents.namespace = "Application" resources.odm.config.proxyDir = APPLICATION_PATH "/cache/proxies" resources.odm.config.proxyNamespace = "proxies" resources.odm.config.hydratorDir = APPLICATION_PATH "/cache/hydrators" resources.odm.config.hydratorNamespace = "hydrators" [staging : production] [testing : production] phpSettings.display_startup_errors = 1 phpSettings.display_errors = 1 [development : production] phpSettings.display_startup_errors = 1 phpSettings.display_errors = 1 resources.frontController.params.displayExceptions = 1
  • 30. Base Controller ā€¢ Provide an easy method to access the DocumentManager, and perhaps a service layer / repository ā€¢ Not using an action helper because we will be likely to be using this tightly everywhere, so it avoids writing _helper a few hundred times! ā€¢ You could use an action helper and use IOC or similar to replace this, this is for simplicity
  • 31. <?php namespace LupiController; Base Controller abstract class Action extends Zend_Controller_Action { /** * @var Zend_Application */ Override the constructor at this point! protected $bootstrap; /** * @var DoctrineODMMongoDBDocumentManager */ protected $dm; Itā€™s useful to leave public function __construct(Zend_Controller_Request_Abstract $request, Zend_Controller_Response_Abstract $response, array $invokeArgs = array()) init() for the ļ¬nal { $this->setRequest($request) ->setResponse($response) implementation so ->_setInvokeArgs($invokeArgs); $this->_helper = new Zend_Controller_Action_HelperBroker($this); $this->dm = $this->getBootstrap()->getResource('odm'); you donā€™t need to $this->init(); } remember to always public function getBootstrap() { if (null === $this->bootstrap) { call parent::init() $this->bootstrap = $this->getInvokeArg('bootstrap'); } return $this->bootstrap; } }
  • 32. Simpliļ¬ed controller code <?php use LupiController as controller; class IndexController extends controllerAction { Common repository for /** * @var DoctrineODMMongoDBDocumentRepository */ the controller, set it in protected $repository; public function init() the init { $this->repository = $this->dm->getRepository('ApplicationBlogPost'); } public function indexAction() { $post = $this->repository->find('4dde4067fbd2237df1000000'); $comment = new ApplicationBlogComment(); $comment->setEmail('foo@test.com') ->setComment('nice post!'); $post->addComment($comment); $this->dm->persist($post); $this->dm->flush(); } }
  • 33. Simpliļ¬ed controller code <?php use LupiController as controller; class IndexController extends controllerAction { Common repository for /** * @var DoctrineODMMongoDBDocumentRepository */ the controller, set it in protected $repository; public function init() the init { $this->repository = $this->dm->getRepository('ApplicationBlogPost'); } public function indexAction() { $post = $this->repository->find('4dde4067fbd2237df1000000'); $comment = new ApplicationBlogComment(); $comment->setEmail('foo@test.com') ->setComment('nice post!'); $post->addComment($comment); $this->dm->persist($post); $this->dm->flush(); } } Nice verbose code!
  • 35. Managing change ā€¢ For adding a new property, mostly, you donā€™t need to do much
  • 36. Managing change ā€¢ The db is schema-less
  • 37. Managing change ā€¢ The db is schema-less ā€¢ You can add properties, without needing to update the old objects until your ready
  • 38. Managing change ā€¢ The db is schema-less ā€¢ You can add properties, without needing to update the old objects until your ready ā€¢ Simply add the property, and update old objects through your usual admin interface
  • 39. Managing change ā€¢ The db is schema-less ā€¢ You can add properties, without needing to update the old objects until your ready ā€¢ Simply add the property, and update old objects through your usual admin interface ā€¢ Objects without the new property will simply have a null value until you change them
  • 40. Managing change Make use of the annotations!
  • 41. Changing a property name From To <?php <?php namespace ApplicationBlog; namespace ApplicationBlog; /** /** * @Document(db="blog", collection="posts") * @Document(db="blog", collection="posts") */ */ class Post class Post { { /** /** * @Id * @Id */ */ private $id; private $id; /** /** * @Field(type="string") * @Field(type="string") */ */ private $name; private $title; /** /** * @String * @String */ */ private $content; private $content; } }
  • 42. Changing a property name From To <?php <?php namespace ApplicationBlog; namespace ApplicationBlog; /** /** * @Document(db="blog", collection="posts") * @Document(db="blog", collection="posts") */ */ class Post class Post { { /** * @Id Add @AlsoLoad /** * @Id */ */ private $id; private $id; /** /** * @Field(type="string") * @Field(type="string") * @AlsoLoad({ā€œnameā€}) */ */ private $name; private $title; /** /** * @String * @String */ */ private $content; private $content; } }
  • 43. Transforming a property From To <?php namespace ApplicationBlog; <?php /** namespace ApplicationBlog; * @Document(db="blog", collection="posts") */ /** class User * @Document(db="blog", collection="posts") { */ /** class User * @Id { */ /** private $id; * @Id */ /** private $id; * @Field(type="string") */ /** private $firstname; * @Field(type="string") */ /** private $fullname; * @Field(type="string") */ /** private $lastname; * @ReferenceMany(targetDocument=ā€ApplicationBlogPostā€) */ /** private $posts; * @ReferenceMany(targetDocument=ā€ApplicationBlogPostā€) } */ private $posts; }
  • 44. Transforming a property From <?php To namespace ApplicationBlog; /** * @Document(db="blog", collection="posts") <?php */ namespace ApplicationBlog; class User { /** /** * @Id * @Document(db="blog", collection="posts") */ */ private $id; class User { /** * @Field(type="string") /** */ * @Id private $firstname; */ private $id; /** * @Field(type="string") */ /** private $lastname; * @Field(type="string") */ /** * @ReferenceMany(targetDocument=ā€ApplicationBlogPostā€) private $fulllname; */ private $posts; /** * @ReferenceMany(targetDocument=ā€ApplicationBlogPostā€) /** * @AlsoLoad({ā€œfullnameā€}) */ */ private $posts; public function populateNameProperties($fullname) } { $name = explode(ā€˜ ā€˜, $fullname); $this->firstname = $name[0]; $this->lastname = $name[1]; Use a method to migrate using } } @AlsoLoad
  • 45. NOTE! ā€¢ When searching, your queries will not know about the old name! ā€¢ Include old and new ļ¬elds in your searches if possible until all data has been migrated
  • 46. NOTE! ā€¢ The ODM is still in BETA3, there are still some glitches, but its well worth having a good look now. ā€¢ http://www.doctrine-project.org/ and follow progress
  • 47. Useful information ā€¢ Oļ¬ƒcial docs: http://www.doctrine-project.org/ docs/mongodb_odm/1.0/en/ ā€¢ Mongodb: http://www.mongodb.org/ excellent intro to mongodb ā€¢ The example sandbox: http://github.com/ bittarman/zf-d2-odm
  • 48. Thanks for listening Catch me on twitter: @Bittarman Slides will be available on slideshare http://slideshare.com/rmauger ZF & Doctrine 2 ODM Doctrine

Editor's Notes

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n