SlideShare una empresa de Scribd logo
1 de 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 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

Más contenido relacionado

La actualidad más candente

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
 
Crafting beautiful software
Crafting beautiful softwareCrafting beautiful software
Crafting beautiful softwareJorn Oomen
 
Drupal Field API. Practical usage
Drupal Field API. Practical usageDrupal Field API. Practical usage
Drupal Field API. Practical usagePavel Makhrinsky
 

La actualidad más candente (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 a 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
 
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
 
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 a 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
 

Último

Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxhariprasad279825
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piececharlottematthew16
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clashcharlottematthew16
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 

Último (20)

Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptx
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piece
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clash
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 

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

Notas del editor

  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