something to do with web development

September 14, 2007

CodeIgniter + Services_JSON

CodeIgniter is my favorite of PHP's MVC-like frameworks: it's portable, well-documented, and easily extensible—few of the libraries I use take much modifying to slip into its glove. Services_JSON is one example of a brilliant library I use to provide CodeIgniter a fast JSONifier.

The Helper

To keep code portable, I don't rely on PEAR to maintain Services_JSON; I keep the library in CodeIgniter's own directory structure. Also, because it isn't formatted according to CodeIgniter's conventions, I wrap Services_JSON inside a helper.

Download Services_JSON from the PEAR site.

To keep your work separated from core code as much as possible, I recommend starting a helpers directory inside application rather than using /system/helpers. CodeIgniter will automatically seek for the created directory.

Put JSON.php inside helpers and then create a new helper, json_helper.php:

// Based on Evan Baliatico's JSON Helper:
// http://www.codeigniter.com/wiki/JSON_Helper/

if(!defined('BASEPATH'))
    exit('No direct script access allowed');

function json_init() {
    // Load Services_JSON code
    if(!class_exists('Services_JSON'))
        require_once(BASEPATH . 'application/helpers/JSON.php');

    // Check/create/return JSON Service.
    if(!isset($GLOBALS['JSON_SERVICE_INSTANCE']))
        $GLOBALS['JSON_SERVICE_INSTANCE'] = new Services_JSON();
    return $GLOBALS['JSON_SERVICE_INSTANCE'];
}

function json_encode($data = null) {
    if($data == null) return FALSE;
    $json = json_init();
    return $json->encode($data);
}

function json_decode($data = null) {
    if($data == null) return FALSE;
    $json = json_init();
    return $json->decode($data);
}

I stripped the code's comments to keep this post short. You can see the original file here.

The View

You'll note that the helper is a very slightly tailored version of Evan Baliatico's JSON Helper. However, we're going to improve slightly on his method and create a dedicated JSON view. I call it simply json:

$this->load->helper('JSON'); 

// RFC4627-compliant header
header('Content-type: application/json');

// Encode data
if(isset($data) && !empty($vars))
    echo json_encode($vars);

The Controller

Here's a sample controller with two methods using the json view: ::get_dynamic takes output from a model and feeds it to the JSON view, while ::get_static exists only as an explanation for people who haven't used Services_JSON before.

class Animaniacs extends Controller {

    function Animaniacs() {
        parent::Controller();
    }

    function index() {
    }

    function get_dynamic() {
        $this->load->model('Animaniacs_model');
        $query = $this->Animaniacs_model->get();
        $this->load->view('json', $query->result_array());
    }

    function get_static() {
        $this->load->view('json', array(
            array(
                'id' => 1,
                'name' => 'Yakko Warner'
            ),
            array(
                'id' => 2,
                'name' => 'Wakko Warner'
            ),
            array(
                'id' => 3,
                'name' => 'Dot Warner'
            ),
        ));
    }

}

I've been using this solution quite a bit. It's a quick deploy and a good example of CI's flexibility.