SlideShare a Scribd company logo
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 Certified 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
• Simplifies your domain, removes the
 persistence logic

• Entities are free to do their job
• Defines 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 config 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
                                                                                  Configuration
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
                                                                                  Configuration
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
                                                                                  Configuration
pluginPaths.Lupi_Resource = APPLICATION_PATH "/../library/Lupi/Resource"

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

; Bootstrap options
                                                                  Minimal config 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 final
    {
        $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;
    }
}
Simplified 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();
    }


}
Simplified 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 fields 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

• Official 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 cliente
Leonardo 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.5
Leonardo Proietti
 
Adding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy ApplicationsAdding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy Applications
Sam 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 triangle
Akihito Koriyama
 
SOLID PRINCIPLES
SOLID PRINCIPLESSOLID PRINCIPLES
SOLID PRINCIPLES
Luciano Queiroz
 
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
Kacper Gunia
 
Taming Command Bus
Taming Command BusTaming Command Bus
Taming Command Bus
Krzysztof Menżyk
 
Oops in php
Oops in phpOops in php
Система рендеринга в Magento
Система рендеринга в MagentoСистема рендеринга в Magento
Система рендеринга в Magento
Magecom 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 middleware
Kuan 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 mocking
Konstantin 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-2011
Alessandro Nadalin
 
Symfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technologySymfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technology
Daniel Knell
 
Intro programacion funcional
Intro programacion funcionalIntro programacion funcional
Intro programacion funcional
NSCoder Mexico
 
Solid principles
Solid principlesSolid principles
Solid principles
Declan Whelan
 
Crafting beautiful software
Crafting beautiful softwareCrafting beautiful software
Crafting beautiful software
Jorn Oomen
 
Field api.From d7 to d8
Field api.From d7 to d8Field api.From d7 to d8
Field api.From d7 to d8
Pavel Makhrinsky
 
Drupal Field API. Practical usage
Drupal Field API. Practical usageDrupal Field API. Practical usage
Drupal Field API. Practical usage
Pavel 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 Apps
Kris 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
 
Doctrine for NoSQL
Doctrine for NoSQLDoctrine for NoSQL
Doctrine for NoSQL
Benjamin Eberlei
 
Doctrine and NoSQL
Doctrine and NoSQLDoctrine and NoSQL
Doctrine and NoSQL
Benjamin Eberlei
 
Migrating to dependency injection
Migrating to dependency injectionMigrating to dependency injection
Migrating to dependency injection
Josh Adell
 
Introducing CakeEntity
Introducing CakeEntityIntroducing CakeEntity
Introducing CakeEntity
Basuke 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 gtk2
Elizabeth Smith
 
Doctrine MongoDB Object Document Mapper
Doctrine MongoDB Object Document MapperDoctrine MongoDB Object Document Mapper
Doctrine MongoDB Object Document Mapper
Jonathan Wage
 
Drupal 8 Services And Dependency Injection
Drupal 8 Services And Dependency InjectionDrupal 8 Services And Dependency Injection
Drupal 8 Services And Dependency Injection
Philip Norton
 
Unittests für Dummies
Unittests für DummiesUnittests für Dummies
Unittests für Dummies
Lars Jankowfsky
 
ZG PHP - Specification
ZG PHP - SpecificationZG PHP - Specification
ZG PHP - Specification
Robert Šorn
 
SPL: The Missing Link in Development
SPL: The Missing Link in DevelopmentSPL: The Missing Link in Development
SPL: The Missing Link in Development
jsmith92
 
Jsp presentation
Jsp presentationJsp presentation
Jsp presentation
Sher Singh Bardhan
 
Advanced php testing in action
Advanced php testing in actionAdvanced php testing in action
Advanced php testing in action
Jace Ju
 
Be pragmatic, be SOLID
Be pragmatic, be SOLIDBe pragmatic, be SOLID
Be pragmatic, be SOLID
Krzysztof Menżyk
 
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
PROIDEA
 
Как получить чёрный пояс по WordPress? v2.0
Как получить чёрный пояс по WordPress? v2.0Как получить чёрный пояс по WordPress? v2.0
Как получить чёрный пояс по WordPress? v2.0
Yevhen Kotelnytskyi
 
ZF2 for the ZF1 Developer
ZF2 for the ZF1 DeveloperZF2 for the ZF1 Developer
ZF2 for the ZF1 Developer
Gary 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 Simple
Alexander Varwijk
 
PHP OOP
PHP OOPPHP OOP
PHP OOP
Oscar Merida
 

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
 
Be pragmatic, be SOLID
Be pragmatic, be SOLIDBe pragmatic, be SOLID
Be pragmatic, be SOLID
 
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
 
Как получить чёрный пояс по 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

Fueling AI with Great Data with Airbyte Webinar
Fueling AI with Great Data with Airbyte WebinarFueling AI with Great Data with Airbyte Webinar
Fueling AI with Great Data with Airbyte Webinar
Zilliz
 
Dandelion Hashtable: beyond billion requests per second on a commodity server
Dandelion Hashtable: beyond billion requests per second on a commodity serverDandelion Hashtable: beyond billion requests per second on a commodity server
Dandelion Hashtable: beyond billion requests per second on a commodity server
Antonios Katsarakis
 
Mutation Testing for Task-Oriented Chatbots
Mutation Testing for Task-Oriented ChatbotsMutation Testing for Task-Oriented Chatbots
Mutation Testing for Task-Oriented Chatbots
Pablo Gómez Abajo
 
A Deep Dive into ScyllaDB's Architecture
A Deep Dive into ScyllaDB's ArchitectureA Deep Dive into ScyllaDB's Architecture
A Deep Dive into ScyllaDB's Architecture
ScyllaDB
 
Astute Business Solutions | Oracle Cloud Partner |
Astute Business Solutions | Oracle Cloud Partner |Astute Business Solutions | Oracle Cloud Partner |
Astute Business Solutions | Oracle Cloud Partner |
AstuteBusiness
 
Freshworks Rethinks NoSQL for Rapid Scaling & Cost-Efficiency
Freshworks Rethinks NoSQL for Rapid Scaling & Cost-EfficiencyFreshworks Rethinks NoSQL for Rapid Scaling & Cost-Efficiency
Freshworks Rethinks NoSQL for Rapid Scaling & Cost-Efficiency
ScyllaDB
 
zkStudyClub - LatticeFold: A Lattice-based Folding Scheme and its Application...
zkStudyClub - LatticeFold: A Lattice-based Folding Scheme and its Application...zkStudyClub - LatticeFold: A Lattice-based Folding Scheme and its Application...
zkStudyClub - LatticeFold: A Lattice-based Folding Scheme and its Application...
Alex Pruden
 
Session 1 - Intro to Robotic Process Automation.pdf
Session 1 - Intro to Robotic Process Automation.pdfSession 1 - Intro to Robotic Process Automation.pdf
Session 1 - Intro to Robotic Process Automation.pdf
UiPathCommunity
 
LF Energy Webinar: Carbon Data Specifications: Mechanisms to Improve Data Acc...
LF Energy Webinar: Carbon Data Specifications: Mechanisms to Improve Data Acc...LF Energy Webinar: Carbon Data Specifications: Mechanisms to Improve Data Acc...
LF Energy Webinar: Carbon Data Specifications: Mechanisms to Improve Data Acc...
DanBrown980551
 
"$10 thousand per minute of downtime: architecture, queues, streaming and fin...
"$10 thousand per minute of downtime: architecture, queues, streaming and fin..."$10 thousand per minute of downtime: architecture, queues, streaming and fin...
"$10 thousand per minute of downtime: architecture, queues, streaming and fin...
Fwdays
 
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdfHow to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
Chart Kalyan
 
Main news related to the CCS TSI 2023 (2023/1695)
Main news related to the CCS TSI 2023 (2023/1695)Main news related to the CCS TSI 2023 (2023/1695)
Main news related to the CCS TSI 2023 (2023/1695)
Jakub Marek
 
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectorsConnector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
DianaGray10
 
“Temporal Event Neural Networks: A More Efficient Alternative to the Transfor...
“Temporal Event Neural Networks: A More Efficient Alternative to the Transfor...“Temporal Event Neural Networks: A More Efficient Alternative to the Transfor...
“Temporal Event Neural Networks: A More Efficient Alternative to the Transfor...
Edge AI and Vision Alliance
 
Christine's Supplier Sourcing Presentaion.pptx
Christine's Supplier Sourcing Presentaion.pptxChristine's Supplier Sourcing Presentaion.pptx
Christine's Supplier Sourcing Presentaion.pptx
christinelarrosa
 
Your One-Stop Shop for Python Success: Top 10 US Python Development Providers
Your One-Stop Shop for Python Success: Top 10 US Python Development ProvidersYour One-Stop Shop for Python Success: Top 10 US Python Development Providers
Your One-Stop Shop for Python Success: Top 10 US Python Development Providers
akankshawande
 
High performance Serverless Java on AWS- GoTo Amsterdam 2024
High performance Serverless Java on AWS- GoTo Amsterdam 2024High performance Serverless Java on AWS- GoTo Amsterdam 2024
High performance Serverless Java on AWS- GoTo Amsterdam 2024
Vadym Kazulkin
 
What is an RPA CoE? Session 1 – CoE Vision
What is an RPA CoE?  Session 1 – CoE VisionWhat is an RPA CoE?  Session 1 – CoE Vision
What is an RPA CoE? Session 1 – CoE Vision
DianaGray10
 
Skybuffer SAM4U tool for SAP license adoption
Skybuffer SAM4U tool for SAP license adoptionSkybuffer SAM4U tool for SAP license adoption
Skybuffer SAM4U tool for SAP license adoption
Tatiana Kojar
 
9 CEO's who hit $100m ARR Share Their Top Growth Tactics Nathan Latka, Founde...
9 CEO's who hit $100m ARR Share Their Top Growth Tactics Nathan Latka, Founde...9 CEO's who hit $100m ARR Share Their Top Growth Tactics Nathan Latka, Founde...
9 CEO's who hit $100m ARR Share Their Top Growth Tactics Nathan Latka, Founde...
saastr
 

Recently uploaded (20)

Fueling AI with Great Data with Airbyte Webinar
Fueling AI with Great Data with Airbyte WebinarFueling AI with Great Data with Airbyte Webinar
Fueling AI with Great Data with Airbyte Webinar
 
Dandelion Hashtable: beyond billion requests per second on a commodity server
Dandelion Hashtable: beyond billion requests per second on a commodity serverDandelion Hashtable: beyond billion requests per second on a commodity server
Dandelion Hashtable: beyond billion requests per second on a commodity server
 
Mutation Testing for Task-Oriented Chatbots
Mutation Testing for Task-Oriented ChatbotsMutation Testing for Task-Oriented Chatbots
Mutation Testing for Task-Oriented Chatbots
 
A Deep Dive into ScyllaDB's Architecture
A Deep Dive into ScyllaDB's ArchitectureA Deep Dive into ScyllaDB's Architecture
A Deep Dive into ScyllaDB's Architecture
 
Astute Business Solutions | Oracle Cloud Partner |
Astute Business Solutions | Oracle Cloud Partner |Astute Business Solutions | Oracle Cloud Partner |
Astute Business Solutions | Oracle Cloud Partner |
 
Freshworks Rethinks NoSQL for Rapid Scaling & Cost-Efficiency
Freshworks Rethinks NoSQL for Rapid Scaling & Cost-EfficiencyFreshworks Rethinks NoSQL for Rapid Scaling & Cost-Efficiency
Freshworks Rethinks NoSQL for Rapid Scaling & Cost-Efficiency
 
zkStudyClub - LatticeFold: A Lattice-based Folding Scheme and its Application...
zkStudyClub - LatticeFold: A Lattice-based Folding Scheme and its Application...zkStudyClub - LatticeFold: A Lattice-based Folding Scheme and its Application...
zkStudyClub - LatticeFold: A Lattice-based Folding Scheme and its Application...
 
Session 1 - Intro to Robotic Process Automation.pdf
Session 1 - Intro to Robotic Process Automation.pdfSession 1 - Intro to Robotic Process Automation.pdf
Session 1 - Intro to Robotic Process Automation.pdf
 
LF Energy Webinar: Carbon Data Specifications: Mechanisms to Improve Data Acc...
LF Energy Webinar: Carbon Data Specifications: Mechanisms to Improve Data Acc...LF Energy Webinar: Carbon Data Specifications: Mechanisms to Improve Data Acc...
LF Energy Webinar: Carbon Data Specifications: Mechanisms to Improve Data Acc...
 
"$10 thousand per minute of downtime: architecture, queues, streaming and fin...
"$10 thousand per minute of downtime: architecture, queues, streaming and fin..."$10 thousand per minute of downtime: architecture, queues, streaming and fin...
"$10 thousand per minute of downtime: architecture, queues, streaming and fin...
 
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdfHow to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
How to Interpret Trends in the Kalyan Rajdhani Mix Chart.pdf
 
Main news related to the CCS TSI 2023 (2023/1695)
Main news related to the CCS TSI 2023 (2023/1695)Main news related to the CCS TSI 2023 (2023/1695)
Main news related to the CCS TSI 2023 (2023/1695)
 
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectorsConnector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
 
“Temporal Event Neural Networks: A More Efficient Alternative to the Transfor...
“Temporal Event Neural Networks: A More Efficient Alternative to the Transfor...“Temporal Event Neural Networks: A More Efficient Alternative to the Transfor...
“Temporal Event Neural Networks: A More Efficient Alternative to the Transfor...
 
Christine's Supplier Sourcing Presentaion.pptx
Christine's Supplier Sourcing Presentaion.pptxChristine's Supplier Sourcing Presentaion.pptx
Christine's Supplier Sourcing Presentaion.pptx
 
Your One-Stop Shop for Python Success: Top 10 US Python Development Providers
Your One-Stop Shop for Python Success: Top 10 US Python Development ProvidersYour One-Stop Shop for Python Success: Top 10 US Python Development Providers
Your One-Stop Shop for Python Success: Top 10 US Python Development Providers
 
High performance Serverless Java on AWS- GoTo Amsterdam 2024
High performance Serverless Java on AWS- GoTo Amsterdam 2024High performance Serverless Java on AWS- GoTo Amsterdam 2024
High performance Serverless Java on AWS- GoTo Amsterdam 2024
 
What is an RPA CoE? Session 1 – CoE Vision
What is an RPA CoE?  Session 1 – CoE VisionWhat is an RPA CoE?  Session 1 – CoE Vision
What is an RPA CoE? Session 1 – CoE Vision
 
Skybuffer SAM4U tool for SAP license adoption
Skybuffer SAM4U tool for SAP license adoptionSkybuffer SAM4U tool for SAP license adoption
Skybuffer SAM4U tool for SAP license adoption
 
9 CEO's who hit $100m ARR Share Their Top Growth Tactics Nathan Latka, Founde...
9 CEO's who hit $100m ARR Share Their Top Growth Tactics Nathan Latka, Founde...9 CEO's who hit $100m ARR Share Their Top Growth Tactics Nathan Latka, Founde...
9 CEO's who hit $100m ARR Share Their Top Growth Tactics Nathan Latka, Founde...
 

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 Certified 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 • Simplifies your domain, removes the persistence logic • Entities are free to do their job • Defines 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 config 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 Configuration 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 Configuration 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 Configuration pluginPaths.Lupi_Resource = APPLICATION_PATH "/../library/Lupi/Resource" ; Library include paths & namespaces includePaths.library = APPLICATION_PATH "/../library" autoloaderNamespaces[] = "Lupi" autoloaderNamespaces[] = "Doctrine" ; Bootstrap options Minimal config 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 final { $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. Simplified 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. Simplified 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 fields 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 • Official 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