OS X: Installing MongoDB and the PHP Mongo Driver

Jan 30 2010

MongoDB is a full-featured object database. Since it is fast, versatile, and schema-less, you can develop a very complex data storage layer without an ORM, and without any tedious coding. For this reason, I have been investigating MongoDB as a storage layer for PHP. Here's how to set up an environment on OS X Snow Leopard.

In this blog we'll do the following:

  • Install MongoDB
  • Add some initial data to MongoDB
  • Install the PHP PECL driver for MongoDB
  • Write a short PHP Script that uses MongoDB
  • Shut down the MongoDB server <!--break--> ## Install MongoDB ##

Begin by going to http://www.mongodb.org/display/DOCS/Downloads and grabbing the latest 64-bit version of MongoDB.

You should get a package with a name something like mongodb-osx-x86_64-1.2.2.tgz.

Next, you can untar that file wherever you like. If this is your first time, it's probably easiest to just untar it in the area where you normally work on code.

$ tar -zxvf  mongodb-osx-x86_64-1.2.2.tgz

When you are done with this command, you should have a directory called mongodb-osx-x86_64-1.2.2. It's contents will look something like this:

$ ls -1
GNU-AGPL-3.0
README
THIRD-PARTY-NOTICES
bin
include
lib

The two parts of MongoDB that we are immediately concerned with are in bin, and they are mongod (the server) and mongo (the CLI client).

Before you can start MongoDB, you need to create a location for it to store databases. By default, it stores them in /data/db. You can create that with a simple command:

$ mkdir -p /data/db

(The -p tells mkdir to make all of the parent directories if they do not already exist.)

Make sure that the OS X user that will run the server has write access to /data/db.

Now all you need to do is start the mongod server.

./bin/mongod &amp;

The ampersand after the command above will detach MongoDB from the terminal. The output from the command above should be something like this:

--help for help and startup options
Sat Jan 30 10:13:50 Mongo DB : starting : pid = 14275 port = 27017 dbpath = /data/db/ master = 0 slave = 0  64-bit 
Sat Jan 30 10:13:50 db version v1.2.2, pdfile version 4.5
Sat Jan 30 10:13:50 git version: 8a4fb8b1c7cb78648c55368d806ba35054f6be54
Sat Jan 30 10:13:50 sys info: Darwin erh2.10gen.cc 9.6.0 Darwin Kernel Version 9.6.0: Mon Nov 24 17:37:00 PST 2008; root:xnu-1228.9.59~1/RELEASE_I386 i386 BOOST_LIB_VERSION=1_37
Sat Jan 30 10:13:50 waiting for connections on port 27017

It should now be running. You can test your new database using the mongo command line client. Here's an example:

$ ./mongo
MongoDB shell version: 1.2.2
url: test
connecting to: test
type "help" for help
Sat Jan 30 10:21:27 connection accepted from 127.0.0.1:59966 #1
>

The list line (>) is the Mongo client's prompt. we can type in commands there:

> help
HELP
    show dbs                     show database names
    show collections             show collections in current database
    show users                   show users in current database
    show profile                 show most recent system.profile entries with time >= 1ms
    use <db name>                set curent database to &lt;db name>
    db.help()                    help on DB methods
    db.foo.help()                help on collection methods
    db.foo.find()                list objects in collection foo
    db.foo.find( { a : 1 } )     list objects in foo where a == 1
    it                           result of the last line evaluated; use to further iterate

Let's see what databases are created by default:

> show dbs
admin
local
test

By default, we are using the test database.

Creating Some Basic Data in MongoDB

We can create a new collection (the MongoDB equivalent of a table) simply by using it. So we are going to create a new collection and add a simple document to it:

db.myCollection.save({test:1});

Now we have a new collection named myCollection. It has one document in it, which is expressed as an object with one attribute:

{
  test: 1
}

Does the syntax of the command above look confusing? Or vaguely familiar? MongoDB's shell uses JavaScript as its operational language (and query language). So to operate on the database, we use the db object, access the myCollection object (which is created on the fly), and execute the collection's save() method.

We pass the save() method a literal object, {test: 1}, which it then stores in the database.

We can retrieve all objects in the collection using the find() method:

db.myCollection.find()
{ "_id" : ObjectId("4b645e832426c6583fbb78db"), "test" : 1 }

The find() method (when executed with no arguments) returns all of the objects in the collection. In this case, it finds only the one that we added. Notice that that object now has an _id attribute that MongoDB generated for us.

From here, you may want to go on and learn more about the MongoDB query language in the online docs (http://www.mongodb.org/display/DOCS/Developer+Zone). We will go on to look at the process of installing the PECL driver so that we can write MongoDB apps in PHP.

The main MongoDB Quick Start guide provides much of the same information here (and got me started), but for more OSes and in less detail.

Installing the PECL Mongo Driver for PHP

Installing the PECL driver for Mongo is simple on OS X Snow Leopard. Assuming you have the XCode suite installed (which provides the necessary .h files), you can simply run this command:

$ sudo pecl install mongo

A few moments later, you should have the mongo driver installed. Now all you need to do is tell PHP to load the extension.

To do this, edit /etc/php.ini:

$ sudo vi /etc/php.ini

(Feel free to use whatever editor you want. I tend to use vi.)

At the bottom of the php.ini file, simply add this line:

extension=mongo.so

Save the file, and the extension should be loaded with each invocation of PHP.

Now from the command line you should be able to verify that the extension is being loaded:

$ php --re mongo

The command above should dump information about the public API for the mongo driver. This API is well-documented and the docs can be accessed online at PHP.net.

Make sure you restart your Apache instance to pick up the new Mongo driver!

$ sudo /usr/sbin/apachectl restart

The command apachectl is not on a normal user's path, so you must specify the entire path to it.

Using the PHP Mongo Driver

Now that we have things configured and we have added a simple collection, let's write a quick PHP command line script that will use the Mongo driver to fetch and print our document:

<?php
// Connect to localhost on the default port.
$con = new Mongo();

// Get a handle on the myCollection collection,
// which is in the 'test' database.
$myCollection = $con->test->myCollection;

// Find everything in our collection:
$results = $myCollection->find();

// Loop through all results
foreach ($results as $document) {

  // Attributes of a document come back in an array.
  $test = $document['test'];

  // Technically, _id is a MongoId object. It can 
  // be automatically converted to a string, though.
  $id = $document['_id'];

  // Print out the values.
  printf("Test Value: %d, ID Value: %s\n", $test, $id);

  // You can also extract the timestamp that this 
  // object was created, since timestamp is encoded in 
  // the id:
  $createdOn = $id->getTimestamp();
  $prettyDate = date('r', $createdOn);

  printf("Created on %s.\n", $prettyDate);
}
?>

The code above is amply documented, but here's a quick description of what it does:

  • Connect to the default database (it will connect to localhost with the default port).
  • Get a handle on the collection we created. Recall that by default our collection was stored in the 'test' database.
  • Find all of the documents ($results) stored in our database.
  • Loop through the results, printing two lines of information for each:
    • The value of the 'test' attribute, and the value of the _id attribute.
    • The date upon which this object was created.

If we run that script, we should see output looking something like this:

Test Value: 1, ID Value: 4b645e832426c6583fbb78db
Created on Sat, 30 Jan 2010 10:29:55 -0600.

With just a few lines of code, we have connected to our database and executed a basic search. From here, the developer documentation at PHP.net and MongoDB.org can get you going with more advanced usage.

Finally, let's look at one final piece of sometimes-overlooked administrivia. Here's how to shut down your MongoDB server when you are done.

Shutting Down a MongoDB Server

There are several ways to shut down your server. If it is running in the foreground, you can just CTRL-C to stop it. Otherwise, the easiest way is to log into the CLI and shut it down from there:

$ mongo
> db._adminCommand("shutdown")