From 42ca256df63af0569eb00ccca62cf079a5f78ad4 Mon Sep 17 00:00:00 2001 From: =?utf8?q?C=C3=A9sar=20D=2E=20Rodas?= Date: Wed, 3 Mar 2010 18:00:36 -0300 Subject: [PATCH] - Improved the Blog model sample - Fixed double updating bug on save() method --- ActiveMongo.php | 13 ++---- sample/blog/App.php | 34 ++++++++++++---- sample/blog/Author.php | 19 +++++++++ sample/blog/Post.php | 107 ++++++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 151 insertions(+), 22 deletions(-) diff --git a/ActiveMongo.php b/ActiveMongo.php index f61763b..222f728 100644 --- a/ActiveMongo.php +++ b/ActiveMongo.php @@ -104,7 +104,7 @@ abstract class ActiveMongo implements Iterator private $_id; // }}} - // string _getCollectionName() {{{ + // string getCollectionName() {{{ /** * Get Collection Name, by default the class name, * but you it can be override at the class itself to give @@ -112,7 +112,7 @@ abstract class ActiveMongo implements Iterator * * @return string Colleciton Name */ - protected function _getCollectionName() + protected function getCollectionName() { return strtolower(get_class($this)); } @@ -189,7 +189,7 @@ abstract class ActiveMongo implements Iterator */ final protected function _getCollection() { - $colName = $this->_getCollectionName(); + $colName = $this->getCollectionName(); return self::_getConnection()->selectCollection($colName); } // }}} @@ -476,19 +476,14 @@ abstract class ActiveMongo implements Iterator $this->pre_save($update ? 'update' : 'create', $obj); if ($update) { $conn->update(array('_id' => $this->_id), $obj); - $conn->save($obj); foreach ($obj as $key => $value) { $this->_current[$key] = $value; } + $this->on_update(); } else { $conn->insert($obj, $async); $this->_id = $obj['_id']; $this->_current = $obj; - } - /* post-save hook */ - if ($update) { - $this->on_update(); - } else { $this->on_save(); } } diff --git a/sample/blog/App.php b/sample/blog/App.php index 3d704e7..a3eb2b5 100644 --- a/sample/blog/App.php +++ b/sample/blog/App.php @@ -8,23 +8,40 @@ ActiveMongo::connect("activemongo_blog"); /* This should be done just once */ ActiveMongo::install(); - +/* Create a new author + * The property country is not defined + * as an AuthorModel property, but it will + * be saved. + */ $author = new AuthorModel; $author->username = "crodas"; -$author->name = "Cesar Rodas"; +$author->name = "Cesar Rodas"; +$author->country = "PY"; $author->save(); +/* Add one blog post */ $post = new PostModel; $post->uri = "/hello-world"; +$post->title = "Hello World"; $post->author = $author; $post->save(); +/* Add another post */ $post = new PostModel; -$post->uri = "/hello-world-1"; +$post->uri = "/yet-another-post"; +$post->title = "Yet another post"; $post->author = $author; +/* add one comment */ +$post->add_comment("testing", "root@foo.com", "testing comment"); +$post->save(); + +/* add another comment */ +$post->add_comment("testing", "root@foo.com", "cool post"); $post->save(); /* Clean up the current the resultset */ +/* same as $post = null; $post = new Post Model */ +/* but more efficient */ $post->reset(); $post->author = $author->getID(); foreach ($post->find() as $bp) { @@ -36,11 +53,12 @@ $author->save(); var_dump("Author profile has been updated"); -/* Clean up the current the resultset */ -$post->reset(); -$post->author = $author->getID(); -foreach ($post->find() as $bp) { - var_dump("Author: ".$bp->author_name); +/** + * List our blog posts in the correct order + * (descending by Timestamp). + */ +foreach ($post->listing_page() as $bp) { + var_dump(array("Author" => $bp->author_name, "Title"=>$bp->title)); } /* delete collections */ diff --git a/sample/blog/Author.php b/sample/blog/Author.php index 8269720..5029ff7 100644 --- a/sample/blog/Author.php +++ b/sample/blog/Author.php @@ -10,6 +10,16 @@ class AuthorModel extends ActiveMongo return 'author'; } + /** + * Username filter. + * + * - It must be unique (handled by MongoDB actually). + * - It can't be changed. + * - It must be /[a-z][a-z0-9\-\_]+/ + * - It must be longer than 5 letters. + * + * @return bool + */ function username_filter($value, $old_value) { if ($old_value!=null && $value != $old_value) { @@ -23,8 +33,17 @@ class AuthorModel extends ActiveMongo if (strlen($value) < 5) { throw new Exception("Username too short"); } + + return true; } + /** + * When an User updates his profile, we need to + * make sure that every post written by him is also + * updated with his name and username. + * + * @return void + */ function on_update() { $post = new PostModel; diff --git a/sample/blog/Post.php b/sample/blog/Post.php index e5f96f9..23aa935 100644 --- a/sample/blog/Post.php +++ b/sample/blog/Post.php @@ -6,7 +6,74 @@ class PostModel extends ActiveMongo public $uri; public $author; public $comment; + public $ts; + const LIMIT_PER_PAGE=20; + + /** + * Return this collection name. + * + * @return string + */ + function getCollectionName() + { + return 'post'; + } + + /** + * Display the blog posts entries in the correct + * order, getting only the needed columns, and + * adding pagination. + * + * @return PostModel This document + */ + function listing_page() + { + /* Get collection */ + $collection = $this->_getCollection(); + + /* Deal with MongoDB directly */ + $columns = array( + 'title' => 1, + 'uri' => 1, + 'author_name' => 1, + 'author_username' => 1, + 'ts' => 1, + ); + $cursor = $collection->find(array(), $columns); + $cursor->sort(array("ts" => -1))->limit(self::LIMIT_PER_PAGE); + + /* Pagination */ + if (isset($_GET['page']) && is_numeric($_GET['page']) && $_GET['page'] > 0) { + $skip = (int)$_GET['page'] * self::LIMIT_PER_PAGE; + $cursor->skip($skip); + } + + /* Pass our results to ActiveMongo */ + $this->setCursor($cursor); + + return $this; + } + + function pre_save($op, &$obj) + { + if ($op == "create") { + $obj['ts'] = new MongoTimestamp(); + } + } + + + /** + * Author Filter. + * + * Check if we save the Author _id, + * or it throws an exception. + * + * @param mixed &$value Current value + * @param mixed $old_value Past value, used on Update + * + * @return bool + */ function author_filter(&$value, $old_value) { if (!$value instanceof MongoID) { @@ -14,14 +81,22 @@ class PostModel extends ActiveMongo throw new Exception("The author property must be an AuthorModel object"); } $value = $value->getID(); + if ($value === false) { + throw new Exception("The AuthorModel doesn't have any record"); + } } + return true; } - function getCollectionName() - { - return 'post'; - } - + /** + * Update Author information in the Posts. This function + * is trigger when a new Post is created or the Author + * has updated his/her profile. + * + * @param MongoID $id Author ID + * + * @return void + */ function updateAuthorInfo(MongoID $id) { $author = new AuthorModel; @@ -43,15 +118,37 @@ class PostModel extends ActiveMongo return true; } + /** + * A new post must have its author information + * on it. (to avoid multiple requests at render time). + * + * @return void + */ function on_save() { $this->updateAuthorInfo($this->author); } + /** + * Simple abstraction to add a new comment, + * to avoid typo errors at coding time. + */ + function add_comment($user, $email, $comment) + { + $this->comment[] = array( + "user" => $user, + "email" => $email, + "comment" => $comment, + ); + return true; + } + function setup() { $collection = & $this->_getCollection(); $collection->ensureIndex(array('uri' => 1), array('unique'=> 1, 'background' => 1)); + $collection->ensureIndex(array('author' => 1), array('background' => 1)); + $collection->ensureIndex(array('ts' => -1), array('background' => 1)); } } -- 2.11.4.GIT