Zend Framework and the Doctrine2 MongoDB ODM (ZF1)

  • 8,549 views
Uploaded on

A short introduction to using and integrating the Doctrine 2 ODM for mongodb in your Zend Framework Applications

A short introduction to using and integrating the Doctrine 2 ODM for mongodb in your Zend Framework Applications

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
No Downloads

Views

Total Views
8,549
On Slideshare
0
From Embeds
0
Number of Embeds
3

Actions

Shares
Downloads
149
Comments
1
Likes
5

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n

Transcript

  • 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 ORMBut works with a Document Database
  • 7. What is the ODM? Object Document Mapper Similar to an ORMBut 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 ODMPersistence operations revolve around the Document Manager Mapping of properties is carried out through annotations in your entities, or through xml/yaml mappings
  • 12. <?phpnamespace 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. <?phpnamespace 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 blogswitched to db blog> db.posts.find();{ "_id" : ObjectId("4dde4067fbd2237df1000000"), "title" : "My Interesting Post", "content" : "I have somethnng veryinteresting 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 veryinteresting 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();>
  • 18. Available Annotationshttp://www.doctrine-project.org/docs/mongodb_odm/1.0/en/ reference/annotations-reference.html
  • 19. Available Annotationshttp://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)
  • 20. Integrating with ZF
  • 21. Integrating with ZFExample 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 settingsphpSettings.display_startup_errors = 0phpSettings.display_errors = 0; Set Plugin path for lupi mongoodm resource ConfigurationpluginPaths.Lupi_Resource = APPLICATION_PATH "/../library/Lupi/Resource"; Library include paths & namespacesincludePaths.library = APPLICATION_PATH "/../library"autoloaderNamespaces[] = "Lupi"autoloaderNamespaces[] = "Doctrine"; Bootstrap optionsbootstrap.path = APPLICATION_PATH "/Bootstrap.php"bootstrap.class = "Bootstrap"; Applicaiton Setupappnamespace = "Application"resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"resources.frontController.params.displayExceptions = 0; ODM settingsresources.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 = 1phpSettings.display_errors = 1[development : production]phpSettings.display_startup_errors = 1phpSettings.display_errors = 1resources.frontController.params.displayExceptions = 1
  • 28. [production]; PHP settingsphpSettings.display_startup_errors = 0phpSettings.display_errors = 0; Set Plugin path for lupi mongoodm resource ConfigurationpluginPaths.Lupi_Resource = APPLICATION_PATH "/../library/Lupi/Resource"; Library include paths & namespacesincludePaths.library = APPLICATION_PATH "/../library"autoloaderNamespaces[] = "Lupi"autoloaderNamespaces[] = "Doctrine"; Bootstrap options Tell it where to load the plugin resourcebootstrap.path = APPLICATION_PATH "/Bootstrap.php"bootstrap.class = "Bootstrap"; Applicaiton Setupappnamespace = "Application"resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"resources.frontController.params.displayExceptions = 0; ODM settingsresources.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 = 1phpSettings.display_errors = 1[development : production]phpSettings.display_startup_errors = 1phpSettings.display_errors = 1resources.frontController.params.displayExceptions = 1
  • 29. [production]; PHP settingsphpSettings.display_startup_errors = 0phpSettings.display_errors = 0; Set Plugin path for lupi mongoodm resource ConfigurationpluginPaths.Lupi_Resource = APPLICATION_PATH "/../library/Lupi/Resource"; Library include paths & namespacesincludePaths.library = APPLICATION_PATH "/../library"autoloaderNamespaces[] = "Lupi"autoloaderNamespaces[] = "Doctrine"; Bootstrap options Minimal config to get startedbootstrap.path = APPLICATION_PATH "/Bootstrap.php"bootstrap.class = "Bootstrap"; Applicaiton Setupappnamespace = "Application"resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"resources.frontController.params.displayExceptions = 0; ODM settingsresources.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 = 1phpSettings.display_errors = 1[development : production]phpSettings.display_startup_errors = 1phpSettings.display_errors = 1resources.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. <?phpnamespace LupiController; Base Controllerabstract 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<?phpuse 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<?phpuse 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!
  • 34. Managing change
  • 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 changeMake use of the annotations!
  • 41. Changing a property name From To<?php <?phpnamespace 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 Postclass 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/rmaugerZF & Doctrine 2 ODM Doctrine