Zend Framework + MongoDB + Morph

Posted: February 26th, 2011 | Author: | Filed under: MongoDB, PHP, Tutorials | 4 Comments »

This is not another SQL vs noSQL rant. I’m not here to defend one or the other and there are plenty of articles written about this very topic. I just wanted to share my personal experience with using MongoDB in Zend Framework using the Morph library.

The most painful part of programming for me is the CRUD of persistant data storage. I can’t think of anything more tedious than creating complex SQL schemas, modelling my data, creating getters and setters etc. I know what data I need to store, retrieve and manipulate and I just want to dive into the code without having to waste hours setting up the database. But the real pain starts during iterations where I have to update the schema and deploy the changes to all environments – or worse, roll back schema changes.

After discovering Django‘s modelling layer I realised what I was missing out on. It made perfect sense to me. Make your models first and have the SQL managed by the framework automatically. Of course this was still quite annoying because model/schema changes were quite difficult to do but at least there was no need for CRUD because you get it all for free. No more complex join queries!

Once I started using Google App Engine‘s Datastore I was free of SQL’s constraints. I created my data models and if I needed to add an extra field to my model I could do so without having to worry about running ALTER TABLE commands.

I’ve spent the last 2 years working with another noSQL system, CouchDB and again, I’m not here to compare the two but MongoDB just seems more suitable for my needs. I have now integrated MongoDB into my Zend Framework projects and it’s hard to imagine how I ever lived without it. It’s ridiculously easy to set up, no CRUD and it’s incredibly intuitive. Here’s how:

1. Download and run MongoDB service
Once you have downloaded the binaries, create a directory where you want your data stored. Remember MongoDB creates individual BSON (binary JSON) documents for each record. You can start the service by running:

shell> mongod --dbpath=/path/to/my/mongodata

2. Install the MongoDB PHP extension
After downloading the extension install and add to your php.ini

3. Download the Morph library
Add the Morph lib to your PHP include path (or autoload in ZF)

You are ready to go. Let’s try and use it in a simple ZF project. Let’s say we want to create a shopping cart that holds a product name, quantity, price and colour.

Create a “Cart.php” class in /models directory and extend Morph_Object.

1
2
3
4
5
6
7
8
9
10
11
12
13
class Application_Model_Cart extends Morph_Object
{
 
    public function __construct($id = null)
    {      
        parent::__construct($id);
        $this->addProperty(new Morph_Property_String('title'))
             ->addProperty(new Morph_Property_Integer('quantity'))
             ->addProperty(new Morph_Property_Float('price'))
             ->addProperty(new Morph_Property_String('colour'));     
    }
 
}

Believe it or not, you’ve just finished modelling your data and CRUD and you’re ready to store and retrieve data immediately without having to run any SQL generation scripts. Brilliant.

To store data in say a controller, you would do something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// instantiate mongo and select your db
$mongo = new Mongo();
Morph_Storage::init($mongo->selectDB('shoppingDB'));
 
// instantiate your cart        
$cart = new Application_Model_Cart();
 
// add data
$car->title = 'Something cool';
$cart->quantity = 12;
$cart->price = 15.50;
$cart->color = "Red";
 
// save the data
$cart->save();

You’ve just saved your first record and didn’t have to create individual getters and setters for your fields.

Getting the data out is just as simple:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// instantiate mongo and select your db
$mongo = new Mongo();
Morph_Storage::init($mongo->selectDB('shoppingDB'));
 
// instantiate your cart        
$cart = new Application_Model_Cart();
 
// create a query
$query = new Morph_Query();
$query->property('price')->greaterThan(1.0);
 
// find records matching query
$result = $cart->findByQuery($query);
 
// send results down to view layer        
$this->view->result = $result;

Check the documentation for the full list of query options. Now loop through the results in your view layer and output the data:

1
2
3
<? foreach($this->result as $item): ?>
    <li><?=$item->title?></li>
<? endforeach ?>

The best part is that since our data store is schema-less, you are free to manipulate your data structure like adding a new field. You do this by simply adding a new property to the Cart class. That’s it.

I hope this post demonstrates the benefits of using noSQL in your PHP projects. Naturally you can use the above in any PHP framework. I just used ZF as an example.

Happy noSQL coding!

4 Comments »
  • http://www.google.com/profiles/jeremy.ottevanger Jeremy

    Nice one Giv. Very timely too: I was at PHPUK on Friday and the NoSQL session was by far the most inspiring for me (along with the MapReduce one). Now seeing how easy it is to hook into MongoDB makes it even more tempting to give it a whirl. At least, once I’ve got a little further up the many other learning curves I’m currently on…

    • Anonymous

      Yes it’s quite a lot of fun. I was hoping to attend PHPUK but wasn’t able to. Take care.

  • Manish

    encounter a problem
    class mongo not found

  • guest

    Morph_Storage::init($mongo->selectDB(‘shoppingDB’));This is not working for me, throwing exception…