Build a simple JSON controller for your web project

Regardless of which database back end your project uses, a JavaScript Object Notation (JSON) controller can simplify your development efforts. Set up a very basic JSON controller that can enhance your next development project.

Thomas Myer (tom@tripledogdaremedia.com), Consultant, Triple Dog Dare Media

Thomas MyerThomas Myer is a consultant, author, and speaker based in Austin, Texas. He runs Triple Dog Dare Media and tweets as @myerman on Twitter. You can reach him at tom@tripledogs.com.



10 August 2010

Also available in Chinese Japanese

Your next PHP/MySQL project might be similar to the last dozen projects you've done: Set up a MySQL database, create your PHP views containing HTML, add JavaScript code and CSS files as needed, connect to the database, extract content from the database to populate your views, and so on. If you're familiar with web development, you know the benefits of separating functional code. For example, you know to avoid entering raw SQL queries directly into your views, and you don't mix up HTML tags inside of functions or classes that extract data from the database.

Frequently used acronyms

  • Ajax: Asynchronous JavaScript + XML
  • CSS: Cascading style sheet
  • CSV: Comma-separated values
  • HTML: Hypertext Markup Language
  • HTTP: Hypertext Transfer Protocol
  • JSON: JavaScript Object Notation
  • REST: Representational State Transfer
  • SQL: Structured Query Language
  • XML: Extensible Markup Language

However, at some point, your project might expand beyond your normal PHP/MySQL comfort level. For example, you might not only have normal web views that require data from a database, but also outside applications (like Facebook) and even mobile devices (perhaps a smartphone) that access that same data.

You might find yourself in a situation where the database changes or requires that you deal with some kind of flat-file XML repository. In these situations, your blind reliance on MySQL might hinder your efforts to complete the project.

Consider putting a RESTful JSON controller into your project and using it as a virtual "traffic cop" that sends requests to and accepts responses from your data source. This article covers the basics of REST and JSON, and shows you one method of setting up the controller. The result is an easy method of data retrieval from a source in a standardized format that you can easily parse with either PHP or JavaScript code.

What is REST?

In a typical REST architecture, a client sends a request to the server, which responds with a representation of the requested resource. A resource can be almost any informational object, like a database or a document, and its representation is usually a formatted document (often XML or JSON) that acts as a snapshot of its current or requested state.

REST resources are typically identified using meaningful URLs that accept different request "verbs"—GET, POST, PUT, and DELETE. These verbs are somewhat analogous to the create-retrieve-update-delete (CRUD) model that many developers are familiar with.

For example, if you want to retrieve data, use a GET request; to create data, a POST request; to update data, a PUT request; and finally, to delete data, a DELETE request.

Another important factor to consider is the response. A RESTful service typically provides two meaningful components in its responses: the response body itself and a status code. Many REST servers actually allow users to specify a response format (such as XML, CSV, serialized PHP, or plain text) either by sending in an ACCEPT parameter or by specifying a file extension (for example, /api/users.xml or /api/users.json). Other REST servers, like the one you're going to implement here, have hard-coded response formats. These are equally acceptable as long as they are documented.

Response codes tend to be HTTP status codes. The beauty of this schema is that you can use existing, well-known status codes to identify errors or successes. A 201 status code (CREATED) is a perfect response to a successful POST request. A 500 error code indicates a failure on your end, but a 400 error code indicates a failure on the client's end (BAD REQUEST). Send a 503 (SERVICE UNAVAILABLE) if something is wrong with the server.

Consider the following example: an application has a data source that contains user information—first name, last name, email address, and Twitter account. If you were setting up a typical PHP application, you'd create a mysql_query() wrapper to extract a listing from the database using an SQL query. You'd also have a bit of PHP code that would call that function and loop through the result set to display the data in the application view.

A simpler approach is to set up a simple REST controller that allows for a GET request to /users/list without any other parameters and that, in turn, calls the proper database function and returns a listing in JSON format. Then, your application can decode that JSON data and loop through it in any way necessary to display the content.

Furthermore, you can test to see whether any parameters are sent in to /users/list. For example, if you send a GET request to /users/list/1, then the response includes just the details for the user with an ID of 1. You can even allow other formats besides JSON, like XML, CSV, or serialized PHP.

A RESTful JSON controller does more for your development efforts than putting an extra layer of functionality between the view and the data source. Consider that your basic PHP view may not be the only thing requesting information. For example, you might request information through an Ajax interface using jQuery, or your users might request it via a smartphone or a Facebook application.

In these cases, a RESTful interface that accepts requests and provides a response in an easy-to-understand (and to predict) format can greatly simplify your development efforts. As the developer in charge of PHP views (or even the iPhone application), you can send requests to a URL and receive a set of expected responses. On the other side of the JSON controller, the application can be hooked up to MySQL, PostgreSQL, an XML file repository, or nothing at all.


What is JSON?

JSON is a lightweight text-based data interchange format that is easy for both humans and computers to digest and consume. At its inception, JSON was designed to represent simple data structures. Although it was originally conceived as a way to transmit JavaScript-friendly data in specific, parsers are now available for it in virtually every computer language. In PHP, a pair of native JSON functions help you do a lot of heavy lifting (json_encode and json_decode). Simply send in an array of data (or even a simple string) to json_encode, and a JSON object will emerge (as shown in Listing 1).

Listing 1. A PHP array vs. a JSON object
$data = array(
	'firstname' => 'Tom', 
	'lastname' => 'Smith', 
	'age' => 40
);

print_r($data);
/* prints 
Array( 
	[firstname] => Tom
	[lastname] => Smith
	[age] => 40
)
*/

echo json_encode($data);

/* prints
	{ "firstname": "Tom",
	  "lastname": "Smith",
	  "age":40
	}	
*/

Notice that the typical PHP array that results from an SQL query (where the keys match database field names and the values match the data) is easily transported as a JSON object. Upon arrival, the data can simply be eval() with JavaScript code (for example, from within an Ajax context), or it can be decoded with json_decode() in PHP to be remade into a data array.

JSON data supports various data types besides objects: strings, null values, numbers (integer or real), Boolean values, and arrays (comma-separated sequences of values enclosed in square brackets). As a result, JSON users experience much flexibility when working with data.

This article will help you build a minimalist JSON REST controller that you can place between your model and view functionality. Once it is built, you can tailor your own expansions to fit your project's objectives.

Building a basic JSON controller

Imagine an application that serves up event information. All of the event information is public, so authentication issues are of no major concern here. Furthermore, the objective is to allow queries about events that are happening today and to use JSON to transport the response back to the request originator. For now, assume the requester is a PHP view page.

First, create a simple database schema for events like the schema shown in Listing 2.

Listing 2. The database schema (MySQL)
CREATE TABLE  `events` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`title` VARCHAR( 255 ) NOT NULL ,
`address` VARCHAR( 255 ) NOT NULL ,
`start_time` DATETIME NOT NULL ,
`description` TEXT NOT NULL
);

Once the database table is functional, enter a few mock data records. Make sure that at least one day has multiple entries scheduled for it.

Next, create a typical PHP model file that connects to this database and identifies the events using an SQL query. If this were a real application, you'd probably separate the database connection script from the rest of it and do all kinds of data validation within your query. Your code might look like Listing 3.

Listing 3. A simple query
$SERVER = 'name';
$USER = 'username';
$PASS = 'pw';
$DATABASE = 'dbname';


if (!($mylink = mysql_connect( $SERVER, $USER, $PASS)))
{
	echo "Sorry, could not connect to DB. Contact your sysadmin for help!";
	exit;
}
mysql_select_db( $DATABASE );


class Events{

	function get_events($day){
		$ret_array = array();
		$sql = "select id,title,address,start_time,description 
				from events where start_time like '$day%'
				order by start_time asc";
		$result = mysql_query($sql);

		while($data = mysql_fetch_object($result)){
			$obj['id'] = $data->id;
			$obj['title'] = $data->title;
			$obj['address'] = $data->address;
			$obj['start_time'] = $data->start_time;
			$obj['description'] = $data->description;

			$ret_array[] = $obj;
		}	

		return $ret_array;
	}
}

When you set up a simple call to this function with a date that you know will retrieve some events, you get the results shown in Listing 4.

Listing 4. Results of running the query
$EVENT = new Events;
$today = '2010-06-17';
$events = $EVENT->get_events($today);

print_r($events);

/* results in
	Array
	(
		[0] => Array
			(
				[id] => 2
				[title] => Event #2
				[address] => 156 My Avenue, MyTown, USA 78727
				[start_time] => 2010-06-17 11:30:00
				[description] => Join us for lunch to hear 
					FABULOUS SPEAKER. 
			)

		[1] => Array
			(
				[id] => 1
				[title] => Event #1
				[address] => 123 My Street, Anytown USA 78727
				[start_time] => 2010-06-17 15:30:00
				[description] => A great event! Hope to see you there!
			)

	)
*/

If you run the same code through json_encode(), you get a portable JSON object (as shown in Listing 5).

Listing 5. JSON data object
[
{"id":"2",
"title":"Event #2",
"address":"156 My Avenue, MyTown, USA 78727",
"start_time":"2010-06-17 11:30:00",
"description":"Join us for lunch to hear FABULOUS SPEAKER. "
},
{"id":"1",
"title":"Event #1",
"address":"123 My Street, Anytown USA 78727",
"start_time":"2010-06-17 15:30:00",
"description":"A great event! Hope to see you there!"
}
]

Your goal is to build a simple controller that will know which model and function to run, and then return a JSON object as a response that is usable on the far end of the transaction. This controller will be very brief and look like Listing 6. Paste all of this code into a file called json.php.

Listing 6. A simple controller
class JSON{

	var $response = '';

	function JSON($model,$function,$params){
		$REQUEST = new $model;
		$data = $REQUEST->$function($params);
		$this->response = json_encode($data);
	}
}

To make this code work, require the model you want to invoke, instantiate the JSON class, and then pass in three parameters: the class name of the model, the function you want to run, and the parameter for that function. This class then invokes that function and gets a response that is run through json_encode().

The final step is to create the file that contains the request for the JSON data. This particular file, which you can call listing.php, can be set up to accept three GET variables (one each for the model, function, and parameter), and then pass those variables to the JSON class (as shown in Listing 7).

Listing 7. The requesting code
//this is the code that contains the model
require 'events.php'; 

//this is the JSON controller
require 'json.php';

//pass in your three GET parameters
$MODEL = $_GET['model'];
$FUNCTION = $_GET['function'];

//check to see if param is passed in
//if not, use today's date in this instance
if (isset($_GET['param'])){
	$PARAM = $_GET['param'];
}else{
	$PARAM = date("Y-m-d");
}				
//invoke 
$JSON = new JSON($MODEL,$FUNCTION,$PARAM);

//access the response variable
echo $JSON->response;

At this point, you can load this file into a browser and get a JSON object similar to the one in Listing 5. You can send the JSON object back through json_decode(), process it with JavaScript code, or leave it as is.

An even better approach to this entire process is to create a path structure that more closely emulates a RESTful server. For example, you can create a directory structure called events/today that houses a file called index.php. By pointing your browser to /events/today, you can get back a JSON feed based on the code in Listing 8 without passing in any GET variables.

Listing 8. Code in /events/today/index.php
require '../../events.php';
require '../../json.php';


$MODEL = "Events";
$FUNCTION = "get_events";
$PARAM = date("Y-m-d");


//invoke 
$JSON = new JSON($MODEL,$FUNCTION,$PARAM);	
echo $JSON->response;

//prints out
[
{"id":"3",
"title":"Test Event 3",
"address":"111 Main Street, Austin TX 78727",
"start_time":"2010-06-10 15:15:00",
"description":"Testing 456."
}
]

Conclusion

Using this approach, you can simplify some of the data extraction requirements for your views and supporting applications. Instead of having to remember all the details of the underlying databases, developers can easily hit URLs and receive the response they seek to move forward with their own work.

Resources

Learn

Get products and technologies

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Web development on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Web development
ArticleID=505760
ArticleTitle=Build a simple JSON controller for your web project
publish-date=08102010