Loading presentation...

Present Remotely

Send the link below via email or IM

Copy

Present to your audience

Start remote presentation

  • Invited audience members will follow you as you navigate and present
  • People invited to a presentation do not need a Prezi account
  • This link expires 10 minutes after you close the presentation
  • A maximum of 30 users can follow your presentation
  • Learn more about this feature in our knowledge base article

Do you really want to delete this prezi?

Neither you, nor the coeditors you shared it with will be able to recover it again.

DeleteCancel

Make your likes visible on Facebook?

Connect your Facebook account to Prezi and let your likes appear on your timeline.
You can change this under Settings & Account at any time.

No, thanks

PHP + MongoDB

Web dev with PHP & MongoDB
by

Alejandro Mercado

on 6 July 2013

Comments (0)

Please log in to add your comment.

Report abuse

Transcript of PHP + MongoDB

MongoDB
PHP + MongoDB
Alejandro Mercado
JSON-style Documents
{ author: 'joe',
created : new Date('03/28/2009'),
title : 'Yet another blog post',
text : 'Here is the text...',
tags : [ 'example', 'joe' ]
}
Example:
amercado@kmmx.mx
http://kmmx.mx/index.php/cursos
MongoDB
is an open source, document-oriented database that supports the concept of flexible schema.
Time for action!
Head on over to the downloads page on the MongoDB official website,
http://www.mongodb.org/downloads.

Click on the download link for the latest stable release under Windows 32-bit.
This will start downloading a ZIP archive:
Instalación
Move the ZIP archive to the C:\ drive and extract
it. Rename the extracted folder (mongodb-win32-i386-x.y.z where x.y.z is
the version number) to mongodb.

Create the folder C:\data\db. Open a CMD prompt window, and enter the
following commands:
C:\> cd \mongodb\bin
C:\mongodb\bin> mongod
Open another CMD prompt window and enter the following commands:

C:\> cd \mongodb\bin
C:\mongodb\bin> mongo
Type show dbs into the shell and hit Enter.
Installing the 64-bit version
The documentation at the MongoDB website recommends that you run the 64-bit version of the system. This is because the 32-bit version cannot store more than 2 gigabytes of data. If you think it is likely that the data in your database will exceed the 2 GB limit, then you should obviously download and install the 64-bit version instead. You will also need an operating system that supports running applications in the 64-bit mode. For the purpose of the practical examples shown in this book, we are just fine with the 32-bit version, you should not worry about that too much.
The instructions for installing MongoDB on an OS X powered Mac machine are the same as those for Linux. You have to download the OS X specific binaries for Mongo (available at http://www.mongodb.org/downloads), and follow the same steps to execute them.
Installing MongoDB on OS X
Alternatively, if you have package managers installed on your OS X (Homebrew or MacPorts), you can use them to install MongoDB.
http://brew.sh/
ruby -e "$(curl -fsSL https://raw.github.com/mxcl/homebrew/go)"
To install MongoDB with HomeBrew use the following command:

$ brew update
$ brew install mongodb
To use MacPorts to install MongoDB use the following command:
$ sudo port install mongodb
Command-line parameters
We can override the default MongoDB settings by passing command-line parameters to the mongod program. For example, the next command tells MongoDB to use C:\mongodb_data as data directory by sending it as a --dbpath argument:
C:\>mongodb\bin\mongod --dbpath C:\mongodb_data
We can see the full list of command-line options by running mongod with the--help option:
C:\>mongodb\bin\mongod –-help
File-based configuration
An alternative to sending all those command-line parameters to mongod manually is to put the required configuration settings in a file and then pass the path of the file as a--config option. For example, consider the following sample configuration file:
dbpath = D:\mongodb_data
logpath = D:\mongodb.log
logappend = true
We store this file to a location, say C:\mongodb.conf.
Now, to start MongoDB with the these settings, we have to enter the next command in the CMD prompt:
C:\>mongodb\bin\mongod --config C:\mongodb.conf
creating databases, collections, and documents
In the mongo shell, enter the following command:
>use myfirstdb
enter the following commands to create documents in a collection named movies
>db.movies.insert({name:"Source Code", genre:"sci-fi", year:2011})
>db.movies.insert({name:"The Dark Knight", genre:"action",
year:2008})
>db.movies.insert({name:"Megamind", genre:"animation", year:2010})
>db.movies.insert({name:"Paranormal Activity", genre:"horror",
year:2009})
>db.movies.insert({name:"Hangover", genre:"comedy", year:2010})
The following command returns all documents from the movies collection:
>db.movies.find()
What is the default port address of MongoDB?
a. 27107
b. 27017
c. 27170
How does a new database get created in MongoDB?
a. By the command create database <databasename>
b. By the command use <databasename>
c. By doing use <databasename> first and then doing db.<collectionname>.insert(<jsondocument>)
To make PHP talk to the MongoDB server, we are going to need the PHP-MongoDB driver.
It is a PHP extension library that manages connection to the MongoDB server and enables you to
perform all kinds of operations on a database through PHP.

Installing the PHP driver for MongoDB
installing PHP driver for MongoDB on Windows
Download the ZIP archive
http://downloads.mongodb.org/mongo-latestphp5.2vc6ts.
zip on your machine and extract it.
Copy the php_mongo.dll file from the extracted folder to the PHP extension directory; this is usually the folder name ext inside your PHP installation.

Open the php.ini file inside your PHP installation and add the following line:
extension=php_mongo.dll

Save the file and close it. Restart the Apache web server

Open up your text editor and add the following code to a new file:
<?php
phpinfo();

Save the file as phpinfo.php inside the DocumentRoot of the Apache web server (the htdocs folder).
php mongodb driver on windows


sudo pecl install mongo
Open your php.ini file and add to it
extension=mongo.so
Mongo driver installation
http://www.php.net/manual/en/mongo.installation.php
Install the PHP Driver on Mac
<?php
$mongoDB = new Mongo();
$database = $mongoDB->selectDB("example");
$collection = $database->createCollection('TestCollection');
$collection->insert(array(test => 'Test OK'));

$retrieved = $collection->find();
foreach ($retrieved as $obj) {
echo($obj['test']);
}
?>
Connecting to the MongoDB server from PHP
http://localhost/test_connection.php
Installing the PHP-MongoDB driver on Unix
In a Unix-based system, the PHP driver for MongoDB can be installed using the pecl (PECL - PHP Extension Community Islam) program. You need to have it installed on your machine, which can be done by using the following command:
sudo pecl install mongo
When the installation is finished, edit the php.ini file (usually found at /etc/php.ini) to add the line:
extension=mongo.so
and then restart Apache.
In case you don't have pecl installed on your machine, you can download the driver source code from GitHub, build it, and install it manually:
$ tar zxvf mongodb-mongdb-php-driver-<commit_id>.tar.gz
$ cd mongodb-mongodb-php-driver-<commit_id>
$ phpize
$ ./configure
$ sudo make install
<?php
try{
$mongo = new Mongo(); //create a connection to MongoDB
$databases = $mongo->listDBs(); //List all databases
echo '<pre>';
print_r($databases);
$mongo->close();
} catch(MongoConnectionException $e) {
//handle connection error
die($e->getMessage());
}
test_connection.php
example.php
When no parameter is passed to the constructor of the Mongo class, it connects to the Mongo server running on localhost, on port 27107 (or whatever value is specified for mongo.default_host and mongo.default_port in php.ini).
Configuring the PHP-MongoDB connection
To connect to a Mongo server listening on port 8888, we will type the following command:

$mongo = new Mongo($server="mongodb://localhost:8888");
CRUD (Create, Read, Update, Delete)
plain user interfaces using HTML/CSS with simple textboxes and buttons
A MongoDB database will store all the content.

A MongoDB powered blog
<?php
$action = (!empty($_POST['btn_submit']) &&
($_POST['btn_submit'] === 'Save')) ? 'save_article'
: 'show_form';
switch($action){
case 'save_article':
try {
$connection = new Mongo();
$database = $connection->selectDB('myblogsite');
$collection = $database->
selectCollection('articles');
$article = array{
'title' => $_POST['title'],
'content' => $_POST['content'],
'saved_at' => new MongoDate()
};
$collection->insert($article);
} catch(MongoConnectionException $e) {
die("Failed to connect to database ".
$e->getMessage());
}
catch(MongoException $e) {
die('Failed to insert data '.$e->getMessage());
}
break;
case 'show_form':
default:
}
?>
blogpost.php

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;
charset=utf-8"/>
<link rel="stylesheet" href="style.css"/>
<title>Blog Post Creator</title>
</head>
<body>
<div id="contentarea">
<div id="innercontentarea">
<h1>Blog Post Creator</h1>
<?php if ($action === 'show_form'): ?>
<form action="<?php echo $_SERVER['PHP_SELF'];?>"
method="post">
<h3>Title</h3>
<p>
<input type="text" name="title" id="title/">
</p>
<h3>Content</h3>
<textarea name="content" rows="20"></textarea>
<p>
<input type="submit" name="btn_submit"
value="Save"/>
</p>
</form>
<?php else: ?>
<p>
Article saved. _id:<?php echo $article['_id'];?>.
<a href="blogpost.php">
Write another one?</a>
</p>
<?php endif;?>
</div>
</div>
</body>
</html>
body {
background-color: #e1ddd9;
font-size: 12px;
font-family: Verdana, Arial, Helvetica, SunSans-Regular,
Sans-Serif;
color:#564b47;
padding:20px;
margin:0px;
text-align: center;
}
div#contentarea {
text-align: left;
vertical-align: middle;
margin: 0px auto;
padding: 0px;
width: 550px;
background-color: #ffffff;
border: 1px #564b47;
}
div#innercontentarea{ padding: 10px 50px; }
div#innercontentarea form input[type=text]{ width: 435px; }
div#innercontentarea form textarea[name=content] { width: 435px; }
style.css
If the blog has been saved successfully, the page reloads with a message Article saved.
The hyperlink on the page takes you back to the form so you can write
more blog posts:
Did you notice that we selected a database and a collection that did not even exist in Mongo?
Creating databases and collections implicitly
This is one of the convenient features of MongoDB, we do not have to run any CREATE DATABASE or CREATE TABLE statement beforehand, as we would have to do in MySQL or any other relational database.

The database and collection namespaces get created on the fly, and we can go ahead and start saving objects.

So selectDB() either selects an existing database or creates it implicitly if it is not there. The same thing goes for selectCollection().
Performing 'safe' inserts
An important thing that you must know about MongoDB is that when you invoke an
insert()
method, the program control does not wait for the response from the MongoDB database.

That is, it just signals MongoDB to insert the document, and then immediately moves on to execute the next statement in the code. The actual insert and pooling of connection is taken care of by MongoDB itself.
This is an asynchronous approach for inserting documents in MongoDB and it is the default behavior.
If we want to change this—that is, we want to wait for the response of the database—we need to send an optional safe=true
argument to the
insert()
method
safe mode
try {
$status = $connection=>insert(array('title' => 'Blog Title', 'content' => 'Blog Content'), array(
'safe' => True
));
echo "Insert operation complete";
} catch (MongoCursorException $e) {
die("Insert failed ".$e=>getMessage());
}
Using safe mode guards us against all kinds of user level errors during inserts. For example, if we try to insert a document with a non-unique _id, a safe insert will raise an exception.

MongoDB may also run out of disk space when inserting documents. Safe inserts check against such potential pitfalls.

In a multi-server setup, that is, when the data is being stored on multiple machines (a replica set), using safe inserts ensures that the data is written on at least one machine.

However, this does not mean we should use safe inserts in all scenarios in a real-world application. Safe inserts incur extra overhead, so they will not be as fast as the regular ones.

Benefits of safe inserts
When doing a 'safe' insert, we can supply an optional timeout parameter, which specifies how long (in milliseconds) the program will wait for a database response when doing an insert:
Specifying a timeout on insert
try {
$collection=>insert($document, array('safe' => True,
'timeout' => True
));
} catch (MongoCursorTimeoutException $e) {
die('Insert timeout expired '.$e=>getMessage());
}
In case the database fails to insert the document within the specified timeout period, the PHP runtime throws a MongoCursorTimeoutException.
Although MongoDB assigns a unique _id to a document upon insertion, we can set the _id field of the document explicitly by ourselves.
This is useful for situations when we want to give each document a unique identifier derived from our own rule.

For example, the following code block creates a hash of the current Unix timestamp appended with the
$username string and sets it as the _id of a document:
Setting the user generated _id
$username = 'Joe';
try{
$document = array('_id' => hash('sha1', $username.time()),
'user' => $username,
'visited' => 'homepage.php');
$collection=>insert($document, array('safe' => True));
} catch(MongoCursorException $e) {
die('Failed to insert '.$e=>getMessage());
}
When setting the _id in this way, we should always do a 'safe' insert. This ensures when there is more than one document in the collection with the same _id, a
MongoCursorException
is thrown while doing the insert.
You may have noticed that we added an extra field named saved_at to the article when we inserted it. The value of saved_at is a MongoDate object, which represents the
ISODate
data type in
BSON
.

When instantiated, a MongoDate gives the current Unix timestamp.
The MongoDate object
retrieving articles from a database
Querying documents in a collection
blogs.php

<?php
try {
$connection = new Mongo();
$database = $connection->selectDB('myblogsite');
$collection = $database-->selectCollection('articles');
} catch(MongoConnectionException $e) {
die("Failed to connect to database ".$e-->getMessage());
}
$cursor = $collection-->find();
?>
blogs.php (continua)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<link rel="stylesheet" href="style.css" />
<title>My Blog Site</title>
</head>
<body> <div id="contentarea">
<div id="innercontentarea">
<h1>My Blogs</h1>
<?php while ($cursor->hasNext()): $article = $cursor->getNext(); ?>
<h2><?php echo $article['title']; ?></h2> <p>
<?php echo substr($article['content'], 0, 200).'...'; ?> </p>
<a href="blog.php?id=<?php echo $article['_id']; ?>">Read more</a>
<?php endwhile; ?>
</div>
</div> </body>
</html>
blog.php

<?php
$id = $_GET['id'];
try {
$connection = new Mongo();
$database = $connection->selectDB('myblogsite');
$collection = $database->selectCollection('articles');
} catch(MongoConnectionException $e) {
die("Failed to connect to database ".$e->getMessage());
}
$article = $collection->findOne(array('_id' =>
new MongoId($id)));
?>
Create another file
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;
charset=utf-8"/>
<link rel="stylesheet" href="style.css" />
<title>My Blog Site</title>
</head>
<body>
<div id="contentarea">
<div id="innercontentarea">
<h1>My Blogs</h1>
<h2><?php echo $article['title']; ?></h2>
<p><?php echo $article['content']; ?></p>
</div>
</div>
</body>
</html>
Navigate to blogs.php
click on readme
The Mongo Query Language
Data is retrieved from MongoDB using the Mongo Query Language.

Queries are expressed as JSON objects (or BSON objects to be more correct), which are passed as arguments to the find() method. For example, the next query applied in mongo shell, gets all documents from a collection named movies that have their genre fields set to 'sci-fi':
>db.movies.find({"genre":"sci-fi"})
{ "_id" : ObjectId("4db439153ec7b6fd1c9093ec"), "name" : "Source Code",
"genre" : "sci-fi", "year" : 2011 }
To do the same thing in PHP, we invoke find()on the MongoCollection object representing the movies collection. The query is expressed as an associative array:
//get all movies where genre == sci-fi
$moviesCollection->find(array("genre" : "sci-fi"));
We can also specify multiple query parameters:

//get all movies where genre is comedy and year is 2011
$moviesCollection->find(array('genre' => 'comedy', 'year' => 2011));
When we don't pass any query arguments to find(), it gets an empty array by default (an empty JSON object in MongoDB) and matches all documents in the collection:
//get ALL movies
$moviesCollection->find();
We could have also done $moviesCollection->find(array()), this also returns all
documents (find() receives an empty array as a default parameter).
A query in MongoDB, performed with find(), returns a cursor. We can iterate over this cursor to retrieve all the documents matched by the query. In PHP, the return value of the find() method is a MongoCursor object. In the following code snippet, we get all movies of the action genre and iterate over them in a while loop:
The MongoCursor object
$cursor = $movieCollection->find(array('genre' => 'action'));
while ($cursor->hasNext()) {
$movie = $cursor->getNext();
//do something with $movie
…………………………………………….
}
The hasNext() checks whether or not there are any more objects in the cursor. getNext() returns the next object pointed by the cursor, and then advances the cursor. The documents do not get loaded into memory unless we invoke either getNext() or hasNext() on the cursor, this is good for keeping the memory usage low.
We can do this in a foreach loop as well:

$cursor = $movieCollection->find(array('genre' => 'action'));
if ($cursor->count() === 0) {
foreach ($cursor as $movie) {
//do something with $movie
}
}
The count() method of the MongoCursor returns the number of objects in the cursor. We check if this number is zero (which means no matching results found), so that we can just skip the execution of the foreach section.
We can use the built-in iterator_to_array() function in PHP to change the cursor returned by the query into an array. The array contains all the objects in the cursor, and we can access them or iterate over them
the same way we do with a regular array in PHP. Programmers who find the cursor approach a little too difficult prefer this trick.
Returning documents in an array
$cursor = $movieCollection->find({'genre': 'action'});
$array = iterator_to_array($cursor);
if (!empty($array)) {
foreach($array as $item){
//do something with $item
…………………………………………..
}
}
However, there is a downside of using iterator_to_array(). If the size of the data returned is very large, let's say 1 GB, using iterator_to_array() may lead to a major performance decrease, as PHP will try to load the entire data into memory. So you should avoid using this approach unless you are sure that the dataset is reasonably small.
In addition to doing queries based on equality, we can also do conditional queries in MongoDB using the conditional operators ($gt/$gte, $lt/$lte, $ne, and so on) of the Mongo query language. The next few lines of code demonstrate the uses of such operators:
Conditional Queries
//get all items with field 'x' greater than 100
$collection->find(array('x' => array('$gt' => 100)));
//get all items with field 'x' lower than 100
$collection->find(array('x' => array('$lt' => 100)));
//get all items with field 'x' greater than or equal to 100
$collection->find(array('x' => array('$gte' => 100)));
//get all items with field 'x' lower than or equal to 100
$collection->find(array('x' => array('$lte' => 100)));
//get all items with field 'x' between 100 and 200
$collection->find(array('x' => array('$gte' => 100, '$lte' => 200)));
//get all items with field 'x' not equal to 100
$collection->find(array('x' => array('$ne' => 100)));
Important!
When using the MongoDB conditional query operators in PHP (or any special
operator that has $ as a prefix), we must use the operator within single quotes (') and not
double quotes (").
//Using single quotes (') is ok.
$collection->find(array('x' => array('$gt' => 100)));
//$ is escaped within double quotes (")
$collection->find(array('x' => array("\$gt" => 100)));
//this will cause an error
$collection->find(array('x' => array("$gt" => 100)));
Visit
http://www.mongodb.org/display/DOCS/
Advanced+Queries#AdvancedQueries-ConditionalOperators

to learn some more
of these conditional operators in Mongo.
Full transcript