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.
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
- Learn more about JSON.
- Read more about JSON documentation from the PHP site.
- The developerWorks Web development zone specializes in articles covering various web-based solutions.
- Stay current with developerWorks' technical events and webcasts.
- Watch developerWorks on-demand demos ranging from product installation and setup for beginners to advanced functionality for experienced developers.
Get products and technologies
- Download IBM product evaluation versions or explore the online trials in the IBM SOA Sandbox and get your hands on application development tools and middleware products from DB2®, Lotus®, Rational®, Tivoli®, and WebSphere.
Discuss
- Create your My developerWorks profile today and set up a watchlist on JSON. Get connected and stay connected with My developerWorks.
- Find other developerWorks members interested in web development.
- Web developers, share your experience and knowledge in the Web development group.
- Share what you know: Join one of our developerWorks groups focused on web topics.
- Roland Barcia talks about Web 2.0 and middleware in his blog.
- Follow developerWorks' members' shared bookmarks on web topics.
- Get answers quickly: Visit the Web 2.0 Apps forum.
Comments
Dig deeper into Web development on developerWorks
- Overview
- New to Web development
- Technical library (tutorials and more)
- Forums
- Open source projects
- Events
developerWorks Premium
Exclusive tools to build your next great app. Learn more.
developerWorks Labs
Technical resources for innovators and early adopters to experiment with.
IBM evaluation software
Evaluate IBM software and solutions, and transform challenges into opportunities.
Thomas 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 