Writing a simple blog with Zend Framework and mongoDB

This post came about after a recent experience starting to extend a personal website of mine. It's a simple site that I started writing in the Zend Framework some years ago and which I work on, occasionally. With it I enjoy that complete creative freedom that often only comes with something that's all your own. On that site, I've wanted to have a blog for quite some time and recently I have started learning about and working with NoSQL databases, including CouchDB and m****ongoDB.

What's more, I've been building a simple fileserver with mongoDB and Zend Framework as a first test of putting the two together. As that project is going very well, I thought that I should apply what I'd done there to create an ultra-simple blog. So this post will document some of the process, giving you a simple introduction into combining the two technologies. This is not going to be too detailed, just a warm up, but I'm planning to write a couple of posts building upon this one.

What's Mongo? If you need a great introduction to Mongo? Grab a copy of the Little MongoDB Book by Karl Seguin.

Post Requirements

What you're going to need to follow along with this post is:

  • Working knowledge of the Zend Framework - version 1.1o or above - with the **zf **tool available
  • A working development environment with a web server, such as Apache 2
  • An installation of mongoDB
  • An open mind to try new things :-)

Background on Mongo

But first a quick bit of background on mongoDB. According to the official site, MongoDB is:

MongoDB bridges the gap between key-value stores (which are fast and highly scalable) and traditional RDBMS systems (which provide rich queries and deep functionality). MongoDB (from "humongous") is a scalable, high-performance, open source, document-oriented database.

It's written in C++ and sports the following features:

  • Document-oriented storage
  • Full index support
  • Replication and High-Availability
  • Auto-Sharding
  • Querying
  • Fast In-Place updates
  • Map/Reduce and
  • GridFS

All in all, this makes it a good system if you're looking for an alternative from traditional RDBMS's.

PHP Libraries

There are a number of high-quality, freely available, PHP libraries, including the PHP extension, Zend_NoSQL_Mongo and Shanty-Mongo. For this post, I've settled on Shanty-Mongo as it integrates very quickly with Zend Framework and is pretty feature rich. I'll not get in to too much detail about it here, as you can find out lots more on the website.

Setting up the Base Project

As the key focus of the project is more about mongoDB rather than Zend Framework, I'll assume a lot of prior knowledge of how to setup and manage the project component. However to assist getting everything up and running quickly, run the following commands to get the base project directory ready to go. [php] zf create project mini-blog zf create config zf enable layout zf create module posts zf create controller Index 1 posts zf create controller Create 1 posts zf create controller Delete 1 posts zf create controller Update 1 posts zf create controller View 1 posts [/php]

Adding Mongo support to your project

After that grab yourself a copy of Shanty-Mongo from Github. Simply run the following command: [php]git clone git://github.com/coen-hyde/Shanty-Mongo.git[/php] Then add the library/shanty directory, in the uncompressed file, to the library directory of your project. Then, in your application.ini, add the library to the project's namespace in the production section with: [php] autoloaderNamespaces[] = "Shanty_" [/php] ****When that's done, you're ready to start using it. In addition to this, add autoloaderNamespaces[] = "Common_". We will need this for our classes.

Modelling with Mongo

As we covered earlier, Mongo is a document-oriented storage system. So to use it right, you have to think in terms of documents, not rows, tuples, tables and schemas in the like of MySQL or Oracle. This makes it simpler, I believe, to work with Object-Oriented development languages such as PHP. So I've created a document class below that we'll use for our posts. Have  a look at it below and then we'll cover how it works. [php] // a simple class to model a post class Post extends Shanty_Mongo_Document { protected static $_db = &'forum'; protected static $_collection = &'posts'; protected static $_requirements = array( &'author' => &'Required',

'title' => 'Required',<br /> 'body' => 'Required',<br /> 'createdDate' => 'Required',<br /> 'publishedDate' => 'Required',<br /> 'status' => array('Validator:InArray' => array('draft', 'published'),<br /> ));<br /> }<br /> [/php]

The _db property links the document to the database that it will be stored in. The collection is the name of the collection of documents that this one will be a member of. The _requirements array is the method of enforcing document validation constraints. For our post, we're enforcing that the post has an author, title, body, created date, published dateand status. This will help us keep proper document integrity.

Setting up the Post Module

Once the document class is setup, then it's time to flesh out the Posts controller.

Adding Posts

In the add document action after we've validated and processed the form, we'll have available the details for our post. So then we'll create a new Post document, store the information in it and save it. Sounds simple right? It is. Have a look at the code snippet below. [php] public function createAction() { $blogPost = new Common_Blog_Post(); $blogPost->author = $this->_request->getParam(&'author'); $blogPost->title = $this->_request->getParam(&'title'); $blogPost->body = $this->_request->getParam(&'body'); $blogPost->createdDate = $this->_request->getParam(&'createDate'); $blogPost->publishedDate = $this->_request->getParam(&'publishedDate'); $blogPost->status = $this->_request->getParam(&'status'); $blogPost->save(); } [/php] Now this assumes that you've already setup the code to ***build***, ***populate*** and ***process*** a form, which I'll assume is based on Zend_Form along with **Zend_Config **components. I'm glossing over this for this post given that we're not specifically focusing in that area of the framework. So please bear with me in that respect for now.

Updating Posts

Ok, so it's great that we've saved a post, but what about updating one. Not that hard honestly. It's not that much different from adding them. Firstly, you need to instantiate a post if you can find it in the database, which we'll do based on it's title, in the database. Then, once you have the document, update the properties of it as required, then save it. That's it. So let's have a look at some sample code. [php] public function updatePost() { // attempt to open a post if we can find it $blogPost = Common_Blog_Post::fetchOne( array(&'title' => $this->_request->getParam(&'title')) ); // we found the post, so let's update the properties $blogPost->author = $this->_request->getParam(&'author'); $blogPost->title = $this->_request->getParam(&'title'); $blogPost->body = $this->_request->getParam(&'body'); $blogPost->createdDate = $this->_request->getParam(&'createDate'); $blogPost->publishedDate = $this->_request->getParam(&'publishedDate'); $blogPost->status = $this->_request->getParam(&'status); $blogPost->save(); } [/php]

The fetchOne method, which is inherited from the base Shanty_Mongo_Document class, will return a document if it finds one. This really helps us keep this simple. There are a variety of other methods, but we'll leave that for later posts.

Deleting Posts

Ok, so we've covered creating and updating posts. What about removing posts. As with the updatePost action, the deletePost action will use the findOne method to attempt to find and load an existing post, based on the post title. If we do find it, then we run the delete method on it. It should be noted that when we take a document out of one database, any connected databases will remove the document when the next replication process occurs. We don't need to write any extra code to make this happen. What a relief. So what's the code? [php] public function deletePost() { // attempt to open a post if we can find it $blogPost = Common_Blog_Post::fetchOne( array(&'title' => $this->_request->getParam(&'title'))); // we found the post, so let's delete it $blogPost->delete(); } [/php]

Viewing Posts

Well, not much left to go now. So let's look at the list item - viewing a list of posts. For this, we're going to use the &'all&' method. This will return a Shanty_Mongo_Iterator_Cursor object that allows us to iterate over a collection of our posts. Nice and simple. What we'll do in our viewPosts controller is to assign the object as a view variable and then iterate over it in our view template. Have a look at the code below for a sample. [php] public function viewAction() { // attempt to open a post if we can find it $blogPosts = Common_Blog_Post::all();
// assign the object as a view variable
$this->view->posts = $blogPosts;

Now in the view template: [php] title; ?>

body; ?>


It really is that simple.

Winding Up

Now this article should have given you a introductory idea of just how easy it is to integrate MongoDb and the Zend Framework, specifically with the Shanty-Mongo library. I appreciate that there are a lot of things that I've not covered here, like the forms, proper security and more thorough validation. I've also not gone in to a lot of detail about the wide variety of features that are available with MongoDB, such as storing documents and exactly how replication works. But I hope that I've whet your appetite for learning more.

Stay tuned. In the next post, I'm going to get in to a bit more detail about storing files and some of the deeper mechanics of MongoDB and the Shanty-Mongo library. After that we'll get in to some of the fun of GridFS.

Further Reading

If you liked what you read and would like to see more, please retweet it, or give it a like on facebook **or even give it some **digg love.

till next time,


About Matthew

Matthew Setter Matthew Setter is a PHP & Zend Framework specialist. If you're in need of a custom software application, need to migrate an existing legacy application, or want to know your current application's GPA - get in touch.

Want To Be A Zend Framework Guru?

Drop your email in the box below, and get awesome tutorialsjust like this one — straight to your inbox, PLUS exclusive content only available by email.