MongoDB for the PHP Mind, Part 1
This is part one of a three part blog series by Mitch Pirtle.
We have covered a lot on the blog about MongoDB features, as well as many ways to utilize MongoDB from different languages. This is the first in a series of posts from the perspective of a PHP developer; and covers the gamut from getting started to advanced concepts.
I’m not going to waste the first blog post getting you up and running with MongoDB and the PHP extension, as that whole process is documented quite beautifully:
While we’re at it, you should also take advantage of the online documentation for MongoDB, as well as the reference for the MongoDB extension for PHP.
Getting Started
“So now what?” Oddly enough, I get this question quite frequently, as most folks familiar with relational databases are expecting to create a database, make sure the proper character set is being used, and also enforce login security for database access.
With MongoDB this is greatly simplified, as all MongoDB databases are UTF-8. This is important to note, as some databases arbitrarily pick character sets based on - leaving you with some annoying migration problems to deal with down the road.
We need to secure the database but that is relatively straightforward. At least for development, not using authentication (“trusted mode”) is fine as it should be running on your laptop, with your laptop firewall on. On a public server, either lock down the db with authentication or lock down the network (much like one would do with memcached).
You can dynamically create your database from PHP when you save your first document. This is actually the right place to start for your first experience with MongoDB.
Documents?
Let’s get some quick terminology down so things make more sense. In MongoDB, a table is called a collection, and a row or recordset is called a document.
You are looking at MongoDB most likely wondering what a document database can do for you, and your applications. Unlike relational databases, MongoDB is schema-less, meaning you can store different types of documents in the same collection. This makes MongoDB fantastic for rapid prototyping, but also passes the responsibility to you, our intrepid developer, to make sure to lock down your schema when you finalize your data model.
Why don’t we start with people, since they are the most common user of web applications:
{ "first_name" : "MongoDB", "last_name" : "Fan", "tags" : ["developer","user"] }
This is familiar to a lot of you that work with JavaScript, as it is a JSON document. MongoDB stores your documents as a serialized binary JSON called BSON, giving you the ability to reach inside your documents to find and manipulate them quickly and easily.
There are the ever-present first_name and last_name fields, as well as one called tags which adds a wrinkle to things. This is not stored as a string, but an array of strings. Here is one of MongoDB’s most profound differences with relational databases.
If you are storing arrays inside your documents, you are also able to search by them as well. With the above example, you could get a count of all users in your database who listed developer as one of their tags.
Most importantly, MongoDB can search the tag field regardless of whether it is there or not, or it contains a string, an embedded array, or even an embedded document.
Here is what this document looks like in PHP, I’m calling this first script test.php:
$user = array( 'first_name' => 'MongoDB', 'last_name' => 'Fan', 'tags' => array('developer','user') );
Now let’s quit talking and start doing, as that’s the way I like to learn. I’m going to be verbose, so you understand all the things that are taking place. We can shorten this process later. Add the following to your existing test PHP script:
// Configuration $dbhost = 'localhost'; $dbname = 'test';// Connect to test database
$m = new Mongo("mongodb://$dbhost");
$db = $m->$dbname;

// Get the users collection
$c_users = $db->users;

// Insert this new document into the users collection
$c_users->save($user);

When you run this script (php -f test.php) you might not notice much. What happened in the database? Let’s find out, by firing up the MongoDB client app on the command line:
mpirtle$ mongo test MongoDB shell version: 2.0.6 connecting to: test > show collections; system.indexes users > db.users.findOne() { "_id" : ObjectId("4fd371a4f479d1924f000000"), "first_name" : "MongoDB", "last_name" : "Fan", "tags" : [ "developer", "user" ] }
The test database didn’t exist, as well as the users collection, until we saved that document. I appreciate using findOne() as it formats the JSON output nicely - calling find() will show all results, but no pretty indentation.
There’s a surprise waiting for you in your shiny new document; a field called _id. This is added by MongoDB to ensure a unique key, one that remains unique across a great many shards and clusters of servers.
If you compare the document that is returned by findOne() versus the original data, you will notice that an _id field has been added. The _id field is the unique identifier for a document in a collection. If you don’t provide an _id value, MongoDB will generate a unique ObjectID which is a 12-byte binary value designed to have a high probability of being unique when allocated. An _id value is typically an ObjectID, but you can also specify your own value if there is a more natural primary key. If you’re just starting with MongoDB it’s generally best to use the default ObjectID.
Now it is time to take a look at how to retrieve this data. I’m creating another PHP script called test2.php, and it looks strikingly similar to this:
// Configuration $dbhost = 'localhost'; $dbname = 'test';// Connect to test database
$m = new Mongo("mongodb://$dbhost");
$db = $m->$dbname;

// Get the users collection
$c_users = $db->users;

// Find the user with first_name 'MongoDB' and last_name 'Fan'
$user = array(
 'first_name' => 'MongoDB',
 'last_name' => 'Fan'
);

$user = $c_users->findOne($user);
var_dump($user);

Running this script (php -f test2.php) produces the following output:
mpirtle$ php -f test2.php
array(4) {
'_id' =>
class MongoId#6 (1) {
public $$id =>
string(24) "4fd37aa3f479d1c850000000"
}
'first_name' =>
string(3) "MongoDB"
'last_name' =>
string(5) "Fan"
'tags' =>
array(2) {
[0] =>
string(9) "developer"
[1] =>
string(5) "user"
}
}
The PHP var_dump() output is similar to the shell output for db.users.findOne() above. You will notice that the document created by test2.php has a different ObjectId from the first document that was created in test.php. ObjectIds are non-sequential and are generated from a combination of current timestamp, machine ID, process ID, and a counter field (read the ObjectId specification if you’re curious to know more).
This post hopefully gets your interest piqued with MongoDB and how you can work with it from within your favorite language, PHP. Don’t miss the opportunity to see the most excellent tutorial at php.net.
Conclusion
This article demonstrates a few simple concepts behind MongoDB and how they relate to PHP. In the next series we will talk about more advanced query concepts, different datatypes supported by MongoDB’s BSON, and more.