Archives for May, 2009

8
May

Creating a JSONP Data Provider in PHP

PHP 5.2 or PECL json 1.2 has the ability to convert data structures into JSON:

$data = array('zero', 'one', 'two', 'three');
$json = json_encode($data);
echo $json

However, if you are deploying to a lowered PHP version, either because your hosting provider hasn’t caught up or you’re using Red Hat Enterprise (even the latest 5.3 only has PHP 5.1.2), then you need an alternate solution. I’ve visited http://www.json.org and found a good package: PEAR::Services_JSON (aka pear install Services_JSON). Although it’s in the beta channel, I’ve had good luck with it.

The equivalent code to the above is:

require('Services/JSON.php');
$data = array('zero', 'one', 'two', 'three');
$encoder = new Services_JSON(); 
$json = $encoder->encode($data);
echo $json;

So, that is how you get a JSON string. What if you want to actually emit the JSON in an AJAX-ically useful way? Just add the PHP header function:

require('Services/JSON.php');
$data = array('zero', 'one', 'two', 'three');
$encoder = new Services_JSON(); 
$json = $encoder->encode($data);
header("Content-type: application/json");
echo $json;

Now, for the final touch. Turning out standard JSON into JSONP. The only difference is that we need a JavaScript function definition wrapping the code:

require('Services/JSON.php');
$data = array('zero', 'one', 'two', 'three');
$encoder = new Services_JSON(); 
$json = $encoder->encode($data);
header("Content-type: application/json");
echo 'callbackname (' . $json . ');';

We’ve added a function wrapper around the JSON. That allows for the data to be retrieved using the jQuery API. However, we can’t hard code the callbackname as you see above. We need to use the passed in value from jQuery.

$(function() {
     $.getJSON('provider.php?callback=?',
                    {},  // No additional parameters sent
                    function (data) {
                         // data is now JSON object instantiated from retrieved info
                         alert(data[0]) // Will show 'zero' in the alert that pops up
                    })
     });
});

That strange second question mark in the URL will be replaced by a jQuery created random number string that is expected to be returned in your callback name.

Save the code below as provider.php:

require('Services/JSON.php');
$data = array('zero', 'one', 'two', 'three');
$encoder = new Services_JSON(); 
$json = $encoder->encode($data);
header("Content-type: application/json");
echo $_GET['callback'] . ' (' . $json . ');';

If you are using the outstanding Firebug add-on for Firefox, you’ll be able to see the GET request made by the page containing the jQuery code as well as the JSONP response from the script.

Why go through this trouble? Because we can now put provider.php on any server, regardless of whether the page calling provider.php is in the same domain or not. JSONP gets around the normal AJAX “same domain” restriction.

Now that we have our own provider, we can create simple arrays, complex arrays, and even objects that can be turned into JSON and sent to jQuery enabled pages, regardless of domain.

For additional information, see this IBM Developerworks article. It lists some of the existing JSONP services, including the URL to use with the jQUERY ajax invocations.