At the end of Tutorial 3,
we had successfully set up a Mongo database service on AppFog that will
be available to our running app. We also connected to it via a tunnel
to check that all was working. This tutorial is all about connecting to
our database and doing something useful with it every time a Mxit user
visits our app. Let’s get started!
A word on Mongo
Before we do start inserting records into our database, a word on Mongo is in order. Mongo is the latest generation of what is called NoSQL databases. In Mongo, instead of records being inserted into rows of a table, documents are inserted into collections which are part of a database. If you’ve spent your life doing SQL and queries, then Mongo can seem a little strange. But it’s not very difficult and as we’ll see, PHP’s built-in Mongo API makes the details very straightforward. Here’s a reminder of what we did last time with Mongo:
> u = { mxitid: 'a-mxit-user' }{ "mxitid" : "a-mxit-user" }
> db.mxitusers.insert(u)
> v = {mxitid: 'another-mxit-user'}
{ "mxitid" : "another-mxit-user" }
> db.mxitusers.insert(v)
> show collections
mxitusers
system.indexes
system.users
> db.mxitusers.find()
{ "_id" : ObjectId("515e3b27c54c33504dbcb9f4"), "mxitid" : "a-mxit-user" }
{ "_id" : ObjectId("515e3b4bc54c33504dbcb9f5"), "mxitid" : "another-mxit-user" }
>
u and v are called documents, mxitusers is the collection and db is the database. The values of documents are simply JSON key-value pairs and we’ve set the key to be ‘mxitid.’ And I have to confess, I’ve made a mistake with the data I’ve put into the collection. The mxitid that we can retrieve from a user visiting our application is actually an internal representation and looks something like ‘m123457890’ - not the human friendly “a-mixit-user.” No matter - we’ll be inserting the correct information in our PHP program and it will work with the messaging API. If you want to learn more about Mongo, its excellent tutorial starts here.
Step 1- Connecting via PHP
We’ll be editing our standard index.php as usual. The first thing our app needs to do is to connect to the Mongo service when it loads. That looks like this:
$services_json = json_decode(getenv("VCAP_SERVICES"),true);$mongo_config = $services_json["mongodb-1.8"][0]["credentials"];
$username = $mongo_config["username"];
$password = $mongo_config["password"];
$hostname = $mongo_config["hostname"];
$port = $mongo_config["port"];
$db = $mongo_config["db"];
$name = $mongo_config["name"];
$connect = "mongodb://${username}:${password}@${hostname}:${port}/${db}";
$m = new Mongo($connect);
$db = $m->selectDB($db);
$collection = $db->mxitusers;
The first line grabs some content out of an environment variable
that is set server side when an AppFog app loads. We then extract the
mongo configuration details from it and assign them to some useful
variables. Finally we connect to the Mongo service through PHP’s API and
select the database we’ve been given by AppFog. Then we assign a
handle to our collection called mxitusers.
$visitor = $_SERVER['HTTP_X_MXIT_USERID_R'];
$document = array("mxitid" => $visitor);
$collection->insert($document);
These three lines get the mxitid of the visitor to our page
through the server headers and save them into $visitor. We then create a
new document and insert it into our collection. Now every time someone
visits us as a contact in Mxit, their mxitid (that long string I
described earlier) will be added to the Mongo collection. Try it! Upload
this code as your index.php - remember to surround it with correct php
tags - and then visit your app from within Mxit. If you then tunnel
through to the Mongo database and issue a:
> db.mxitusers.find()
you’ll see it’s adding your mxitid to the collection each time.
Step 2 - Messaging
So now that we can save each user who visits us in a database, let’s send them a message each time they land. We’re going to be using Ashley Kleynhans’ excellent Mxit API for PHP that’s available here. You will need to get the MxitAPI.php from this site - either via git or as a normal download - and then place the file MxitAPI.php in the same directory as your app (in our case testappmxit). Let’s edit index.php some more:
require_once ('MxitAPI.php');
$key = 'f00ff00fabcdabcdabcdg00f';
$secret = 'deadfoofabcd12abcdgoof';
$api = new MxitAPI($key, $secret);
Figure 1: Obtaining your Client Id and Secret for your app
/* Set up the message */
$message = "Thanks for visiting!";
$contains_markup = 'false';
$app = "testappmxt";
$access_token = NULL;
Then we set up some parameters for the API function send_message.
while (is_null($access_token))
{ /* We are sending a message so request access to the message/send scope */
$api->get_app_token('message/send');
$token = $api->get_token();
$access_token = $token['access_token']; // Only attempt to send a message if we have a valid auth token
if (!is_null($access_token))
{
$api->send_message($app,$visitor,$message,$contains_markup);
}
}
Finally we send the message. First we attempt to get authorisation
to send a message. If we get it (the token is not NULL) then we send
the message to our user. The $contains_markup flag tells the API that
the message contains Mxit markup - we’re not doing that this time so
it’s false. If a user adds testappmxt as a contact and opens a conversation, they’ll see something like this:
Figure 2: A look at your use of the Messaging API from within your app!
Step 3 - The Final Program
<?php
require_once ('MxitAPI.php');
$services_json = json_decode(getenv("VCAP_SERVICES"),true);
$mongo_config = $services_json["mongodb-1.8"][0]["credentials"];
$username = $mongo_config["username"];
$password = $mongo_config["password"];
$hostname = $mongo_config["hostname"];
$port = $mongo_config["port"];
$db = $mongo_config["db"];
$name = $mongo_config["name"];
$connect = "mongodb://${username}:${password}@${hostname}:${port}/${db}";
$m = new Mongo($connect);
$db = $m->selectDB($db);
$collection = $db->mxitusers;
$visitor = $_SERVER['HTTP_X_MXIT_USERID_R'];
if ($visitor == '') {
$visitor = "Web user";
}
$document = array("mxitid" => $visitor);
$collection->insert($document);
/* Instantiate the Mxit API */
$key = 'f00ff00fabcdabcdabcdg00f';
$secret = 'deadfoofabcd12abcdgoof';
$api = new MxitAPI($key, $secret);
/* Set up the message */ $message = "Thanks for visiting!";
$contains_markup = 'false';
$app = "testappmxt";
$access_token = NULL;
while (is_null($access_token))
{ /* We are sending a message so request access to the message/send scope */ $api->get_app_token('message/send');
$token = $api->get_token();
$access_token = $token['access_token']; // Only attempt to send a message if we have a valid auth token
if (!is_null($access_token))
{
$api->send_message($app, $visitor, $message, $contains_markup);
}
}
Troubleshooting
During the course of testing this program, I ran into some problems which aren’t particularly obvious to solve so I present the answers here. If you issue an ‘af update testappmxit’, visit your page and AppFog complains like so:
Figure 3: Error message seen if your update command goes wrong.
then you need to restart your PHP app from the AppFog
console. Of course, check also that you haven’t got stuck in an endless
loop!
If you issue an af update testappmxt command and get an error like:
Uploading Application
No such file or directory: -work/mxit/testappmxt/user@host.3458:1365044373
then there is a rogue file left in your application directory that shouldn’t be there. It’s a symbolic link left over from an ‘af’ operation that hasn’t been deleted. Delete it by hand and your update should succeed.
In Tutorial 5, we’ll be using the Billing API to integrate billing into our app. See you then!