beta it republik » Articles

Articles

Untitled Document
Friday, 9 May 2008 | Article

JSON, AJAX, and PHP in One Application

In this article we will create an API written in PHP using the JSON format. We will continue to complete an example that lets us create a searchable user list in AJAX consisting of less then 100 lines of code. Once we complete this article you should be able to identify different areas in your applications where combining these concepts and technologies will add value.


Introduction
The Web has been evolving since its inception. However, it is now evolving at an extremely rapid pace. This is due not only to the increased adoption of broadband but also because of new technologies available to developers. Prior to 2005 advances in web development were confined on the back end systems. While systems were becoming more robust and communication between systems was becoming easier, the front end of these applications hadn’t had much progress.

What’s interesting is that it’s not so much new technology in the browser that’s enabling this rapid evolution of web applications. It’s that we’re beginning to see creative solutions to longstanding problems such as the inability to communicate with the server without reloading the page and security restrictions with cross-domain scripting. We will be looking at several of these creative solutions and putting them together to build a flexible and accessible API that is easily implemented. We’ll be using JSON, AJAX and PHP throughout this article.

Asynchronous JavaScript and XML
AJAX is not a new concept. However, it has recently gained a great deal of popularity. Thanks to web applications like Google Maps and the new Yahoo! Mail beta we are beginning to see the power behind developing web applications with AJAX in mind. The primary benefit of AJAX is that as developers we can take input from the client, interact with the back end, and update parts of the client’s screen without requiring the page to reload. This ability to communicate with the server while allowing the client to continue using the user interface (UI) opens up a new world to web programming. This article will be deviating slightly from the strict definition of AJAX. Instead of using XML to transmit data we will be using JSON.

JavaScript Object Notation
JSON is a lightweight data-interchange format. It is completely language independent though it uses conventions familiar to programmers who have used C, C++, Java, JavaScript, Perl, Python and many other languages. As programmers we often use complex data types to store information for our web applications. There are many common methods for storing data that span across every language. JSON leverages this commonality to use what is known as the object literal form as a format for data interchange. JSON lets you define data natively in one language and pass it to another language that can treat it as a native data type.



Requirements
For this article I will be assuming that you have access to a server with the following:
  • MySQL 4.x+
  • PHP 4.3+ with PEAR support
  • A text editor or IDE and a modern web browser on your desktop


Setting Up the Database
Let’s get started by setting up the database. First you’ll need to create a database and a table. We will go ahead and populate it with some information as well. See Listing 1. Once the database is set up we can move on to the PHP file that will act as our API.

Create the API
Open up your favorite PHP IDE and create a new file, naming it api.php. This is the file that we will call when we need to get information from the server regarding the users table that we created above. We will need to be able to get a list of all the users as well as get search for a user. This file will initially take a URL parameter named service. We can assume this file needs to connect to MySQL each time it is called as well as use PEAR’s JSON library and place the appropriate code at the top of the file. Let’s set the file as shown in Listing 2.

Inside of the getUsers case let’s query the database and get a list of all the users. See Listing 3.

After querying the database, we convert the recordset into an associative array. This way JavaScript will be able to easily use the data in a similar manner to how PHP would use it. In order for JavaScript to be able to use our associative array we will need to encode it in JSON format. We can easily do this by using PEAR’s JSON library. See Listing 4.

Now we have a functioning API that outputs data in JSON format. Before we look at what the API returns let’s see how the api.php file looks so far. See Listing 5.

Let’s go ahead and see what this looks like when we request service. php?service=getUsers. See Listing 6.

Now we have a functioning API that outputs data in JSON format. I took the liberty of formatting the output so that it made a little more sense. But that doesn’t look very useful, does it? We are only half way there but this is a very important part as we will see later.


Listing 1
Set Up the Database
CREATE DATABASE `json_example`;
CREATE TABLE `users` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`email` VARCHAR( 255 ) NOT NULL ,
`first_name` VARCHAR( 255 ) NOT NULL ,
`last_name` VARCHAR( 255 ) NOT NULL ,
`photo` VARCHAR( 255 ) NOT NULL
);
INSERT INTO `users` ( `id` , `email` , `first_name` , `last_
name` , `photo` )
VALUES (NULL , ‘john@example.com’, ‘John’, ‘Smith’, ‘photos/my_friend.jpg’),
(NULL , ‘kelly@example.com’, ‘Kelly’, ‘Murray’, ‘photos/kellymurray.jpg’),
(NULL , ‘tammy@example.com’, ‘Tammy’, ‘Hendricks’, ‘photos/tammyhendricks.jpg’),
(NULL , ‘charles@example.com’, ‘Charles’, ‘Harrington’,‘photos/charlesharrington.jpg’),
(NULL , ‘kevin@example.com’, ‘Kevin’, ‘Vreeland’, ‘photos/kevinvreeland.jpg’),
(NULL , ‘rachel@example.com’, ‘Rachel’, ‘Kaiser’, ‘photos/rachelkaiser.jpg’);


Listing 2
Create the API File (api.php)
<?php
include_once ‘JSON.php’;
$json = new Services_JSON();
$db = mysql_connect(‘localhost’, ‘username’, ‘secret’);
mysql_select_db(‘json_example’, $db);
switch($_GET[‘service’])
{
case ‘getUsers’:
// some code
break;
}
mysql_close($db);
?>


Create the HTML Page
We will be using an HTML document consisting of all the basic tags – HTML, HEAD and BODY. We will add a SCRIPT tag to the HEAD and a DIV tag to the BODY of the document. Create a new file in your IDE and name it client.html and add the following code to it. See Listing 7.

Once we create the HTML document we can move on and create the JavaScript file we are including in the SCRIPT tag.

Create the JavaScript File
Let’s create a JavaScript file named functions.js that we can put all of our JavaScript functions in. Open functions.js in your IDE and define the getUsers function. As mentioned earlier, the getUsers function is going to make a request to our API. There are numerous ways to instantiate an HTTP request with JavaScript but we are going to leverage JavaScript’s ability to manipulate the DOM. We will dynamically append a SCRIPT element into the HEAD of the document. We will go into more detail as to why we are choosing this method later on but for now you just need to know that it works. Let’s go ahead and define the getUsers function. See Listing 8.

This function will need to do three things:
  • Determine what URL we need to request from the API in order to get back a list of all the users
  • Specify the callback function which will be executed once we get a response from the API
  • Load that URL into a dynamic SCRIPT element

Let’s go step-by-step to build the getUsers function; see Listing 9. You can call this function any time to get a list of the available users. Unfortunately nothing visible will happen until we define the callback function. In this case we named the callback function getUsersCallback. The callback function will need to accept one parameter that will be all of the information we requested from the API. getUsersCallback only does the following three things:
  • Accept the data we received from the API as a parameter
  • Loop through the list of users and generate HTML to be displayed to the client
  • Display the HTML to the client

Sounds pretty simple, right? Let’s continue and define the getUsersCallback function step-by-step. See Listing 10.

Now when we call the getUsers function it will connect to the API and then automatically call getUsersCallback. getUsersCallback will automatically generate HTML and display it to the client. The next step is to call the getUsers function once the page loads.

Listing 3
Define the getUsers Case (api.php)
<?php
case ‘getUsers’:
$rs = mysql_query(‘SELECT * FROM users’);
while($user = mysql_fetch_assoc($rs))
{
$output[] = $user;
}
break;
?>


Listing 4
Encode the Output in JSON Format (api.php)
<php
echo $_GET[‘callback’] . ‘(‘ . $json->encode($output) . ‘);’;
mysql_close($db);
?>


Listing 5
Currently Functioning API (api.php)
<?php
include_once ‘JSON.php’;
$json = new Services_JSON();
$db = mysql_connect(‘localhost’, ‘username’, ‘secret’);
mysql_select_db(‘json_example’, $db);
switch($_GET[‘service’])
{
case ‘getUsers’:
$rs = mysql_query(‘SELECT * FROM users’);
while($user = mysql_fetch_assoc($rs))
{
$output[] = $user;
}
break;
}
echo $_GET[‘callback’] . ‘(‘ . $json->encode($output) . ‘);’;
mysql_close($db);
?>



Listing 6
JSON as Output by the API (formatted)
(
[
{
“id”:”1”,
“email”:”john@example.com”,
“first_name”:”John”,
“last_name”:”Smith”,
“photo”:”photos\/my_friend.jpg”
},
{
“id”:”2”,
“email”:”kelly@example.com”,
“first_name”:”Kelly”,
“last_name”:”Murray”,
“photo”:”photos\/kellymurray.jpg”
},
{
“id”:”3”,
“email”:”tammy@example.com”,
“first_name”:”Tammy”,
“last_name”:”Hendricks”,
“photo”:”photos\/tammyhendricks.jpg”
},
...
{
“id”:”6”,
“email”:”rachel@example.com”,
“first_name”:”Rachel”,
“last_name”:”Kaiser”,
“photo”:”photos\/rachelkaiser.jpg”
}
]
);


Listing 7
HTML Page (client.html)
<html>
<head>
<script type=”text/javascript” src=”functions.js”></script>
</head>
<body>
<div id=”content”></div>
</body>
</html>


Listing 8
Define the getUsers Function (functions.js)
function getUsers()
{
// some code
}


Listing 9
Define the getUsers Function (functions.js)
function getUsers()
{
var head = document.getElementsByTagName(‘head’).item(0);
var scriptTag = document.getElementById(‘dynamic_script_tag_id’);
if(scriptTag) head.removeChild(scriptTag);
script = document.createElement(‘script’);
// 1. set the path to the api
// 2. set the callback function as getUsersCallback
script.src = ‘api.php?service=getUsers&callback=getUsersCallback’;
script.type = ‘text/javascript’;
script.id = ‘dynamic_script_tag_id’;
// 3. load the script tag into the DOM
head.appendChild(script);
}


Listing 10
Define the getUsersCallback Function (functions.js)
// 1. define getUsersCallback accepting the users from
// the API as “data”
function getUsersCallback(data)
{
var html = ‘’;
// 2. Loop through the users and generate HTML to be
// displayed
for(i in data)
{
html += ‘<div style=”padding:10px; border-bottom:solid 1px
#dddddd;”>’
+ ‘ <div><img src=”’ + data[i][‘photo’] + ‘” /></div>’
+ ‘ <div style=”font-weight:bold;”>’ + data[i][‘first_name’]
+ ‘ ‘ + data[i][‘last_name’] + ‘</div>’
+ ‘ <div>’ + data[i][‘email’] + ‘</div>’
+ ‘</div>’;
}
// 3. Display the HTML to the client
document.getElementById(‘content’).innerHTML = html;
}



Listing 11
Add an onload Event Handler to the Body Tag (client.html)
<body onload=”getUsers();”>



Fig 1: Results



Walking Through the Code
Now if you load client.html in a web browser you should see a list of users. Hopefully you are beginning to understand how this works. Let’s stop for a moment and review what actually happens when client.html loads in a web browser. The first important line of HTML is the SCRIPT tag. Then we come to the BODY tag that specifies the getUsers function be called once the document is loaded. Lastly we have the DIV tag which has an id of ‘content’.

Once the document finishes loading it executes the getUsers function. Going into functions.js we see that the getUsers function creates a script element and sets a few properties, the most important property being the src property. Then the script element is added to the DOM of client.html. This loads the file as specified by the src property and executes it as JavaScript. The API knows to execute the callback function since we passed it in as a GET variable. Furthermore it passes the content from the users table as a parameter to the callback function. We defined our callback function to accept a parameter that ends up being an array of the users. The callback function loops over each user and generates some HTML which it then loads into the DIV in the BODY of the document.

That’s a lot to grasp if you’ve never done web development in this manner. It’s a different mindset than traditional web development but it has lots of benefits as we’ll see later on.

Adding A Search Feature
No user list is complete without some sort of search functionality. This is where the code we’ve already written starts to pay off. The first thing we should do is to add a case to our API that accepts a name to search for. We will try to match the name entered with the first and last name in the users table. Let’s begin by naming the case ‘searchUsers’.

You’ll notice that this case is almost identical to the getUsers case. The only differences are that it accepts a variable named ‘name’ and it adds that into the SQL. Because the data type returned by this case is identical in structure to the getUsers case we will be able to reuse the callback function. But before we get to that let’s first add the searchUsers function to functions.js. This is what we will call when we want to filter the user list by a value typed in by the client.

Once again you’ll notice that this only slightly differs from the getUsers function. We simply accept a parameter called ‘name’ and pass that in to the API when we specify the src property. Also notice that we kept the callback the same but specified searchUsers as the service.

Let’s add a text field so you can type in someone’s name and have it filter the list of users. We can add it above the DIV that the users get loaded into.

Now if we load up client.html we should initially see all the users from the database. If we type in ‘john’ into the text field and click the ‘search’ button the display will be filtered and only ‘John Smith’ will be shown.

Pretty cool, isn’t it? In about 92 lines of code we created an API, a JavaScript interface to the API and a usable web page that uses both of them to provide a searchable user directory...in AJAX. In addition to having lots of reusable code and an easy way to develop your application using AJAX there are other significant advantages of using this method as a part of your application. We’ll touch on the advantage of having the ability to use this API across domains.



Fig 2: Result of the Search




Crossing Domains
One of the headaches for developers trying to build complex web applications has been the limitations of JavaScript due to cross domain scripting. In an effort to protect the user, browsers have put in restrictions that restrict JavaScript from aaa.com to modify or access the contents of a document at bbb.com. Even true AJAX libraries that are dependent on XMLHTTP are bound to the originating domain. For example, this means it becomes difficult for your application to access Google’s search API because you would have to cross over from your domain to Google’s domain.

JSON provides a simple, yet elegant solution to this problem. In fact the API that we just built can be used across domains. This opens up a lot of doors that enable easy sharing of content. JSON accomplishes this by allowing us to pass data from one domain to another. All the processing and DOM manipulations can still happen on the originating domain. So a document on aaa.com can include

Listing 12
Add a searchUsers Case (api.php)
case ‘searchUsers’:
$name = preg_replace(‘/\W/’, ‘’, $_GET[‘name’]);
$rs = mysql_query(“SELECT * FROM users WHERE first_
name LIKE ‘%{$name}%’ OR last_name LIKE ‘%{$name}%’”);
while($user = mysql_fetch_assoc($rs))
{
$output[] = $user;
}
break;


Listing 13
Add a searchUsers Function (functions.js)
function searchUsers(name)
{
var head = document.getElementsByTagName(‘head’).item(0);
var scriptTag = document.getElementById(‘dynamic_script_tag_
id’);
if(scriptTag) head.removeChild(scriptTag);
script = document.createElement(‘script’);
script.src = ‘api.php?service=searchUsers&name=’+name+’&callb
ack=getUsersCallback’;
script.type = ‘text/javascript’;
script.id = ‘dynamic_script_tag_id’;
head.appendChild(script);
}


Listing 14
Add a Search Form (client.html)
<form onsubmit=”searchUsers(this.nameField.value); return
false;”>
<input type=”text” name=”nameField” size=”12”
/> <input type=”submit” value=”Search” />
</form>



Listing 15
Fully Qualify Paths to the API and Photos (functions.js)
function searchUsers(name)
{
var head = document.getElementsByTagName(‘head’).item(0);
var scriptTag = document.getElementById(‘dynamic_script_tag_
id’);
if(scriptTag) head.removeChild(scriptTag);
script = document.createElement(‘script’);
script.src = ‘http://yourdomain.com/api.php?service=searchUsers
&name=’+name+’&callback=getUsersCallback’;
script.type = ‘text/javascript’;
script.id = ‘dynamic_script_tag_id’;
head.appendChild(script);
}
function getUsers()
{
var head = document.getElementsByTagName(‘head’).item(0);
var scriptTag = document.getElementById(‘dynamic_script_tag_
id’);
if(scriptTag) head.removeChild(scriptTag);
script = document.createElement(‘script’);
script.src = ‘http://yourdomain.com/api.php?service=getUsers&ca
llback=getUsersCallback’;
script.type = ‘text/javascript’;
script.id = ‘dynamic_script_tag_id’;
head.appendChild(script);
}
function getUsersCallback(data)
{
var html = ‘’;
for(i in data)
{
html += ‘<div style=”padding:10px; border-bottom:solid 1px
#dddddd;”>’
+ ‘ <div><img src=”http://yourdomain.com/’ +
data[i][‘photo’] + ‘” /></div>’
+ ‘ <div style=”font-weight:bold;”>’ + data[i][‘first_name’]
+ ‘ ‘ + data[i][‘last_name’] + ‘</div>’
+ ‘ <div>’ + data[i][‘email’] + ‘</div>’
+ ‘</div>’;
}
document.getElementById(‘content’).innerHTML = html;
}


a script from bbb.com that returns data to a function defined on aaa.com and execute it. This does not violate the security restrictions in browsers because the JavaScript that is being executed can be trusted since it comes from the same domain as the document itself.

We only need to add a few minor adjustments to make the API support cross domain scripting. Open up functions.js and modify the src property in both the searchUsers and getUsers functions. You will need to fully qualify the source. See Listing 15.Once you save the files with fully qualified paths, you can open up the API and allow others to easily integrate your content into their application.

Choosing a JSON Library for PHP
There are several ways in which you can configure PHP to support JSON. In this example I used the PEAR library because it should be the most readily available. At the time of this writing there were five JSON libraries available for PHP. PHP-JSON is my personal library of choice for those who have administrative access to your server because it is written as a PHP extension written in C and should outperform the other libraries.

Conclusion
As the Web evolves, we need to evolve as developers. Taking advantage of these new concepts will dramatically increase the value of your application. Web applications that implement AJAX can reduce load on your server as well as increase the responsiveness to the client. PHP has exceptional support for the technologies and concepts covered in this article. Any PHP developer can hit the ground running with numerous tools to choose from.


About the Author

Jaisen Mathai is CTO at FotoFlix, Inc. He was born and raised in Cincinnati, OH where he currently resides. Jaisen has been using PHP for about 7 years along with MySQL and Apache. He has written several articles which appear on line and in print and was a speaker at the 2006 New York PHP Conference.


   Related Links
http://www.json.org/
http://pear.php.net/pepr/pepr-proposal-show.php?id=198
http://www.aurore.net/projects/php-json/


Comment

Name:

Comment:

Captcha Verification !
captcha_image