JSON Error / Exception Messages in Codeigniter 2.0+

The Problem

One of my recent projects required me to build a quick JSON only API to abstract interaction with multiple databases for multiple web applications, as I’d already got some of the logic in Codeigniter I just added Phil Sturgeon’s Codeigniter REST Library. However while this handles all method not found errors when URL routing gets as far as the controller all other errors still appear as HTML, when using curl and attempting to parse as JSON this isn’t helpful.

The Solution

My solution was to extend the core Exceptions class which normally deals with these errors. This is done by creating MY_Exceptions.php in application/core and using something similar to the code below:

<?php defined('BASEPATH') OR exit('No direct script access allowed');

/**
 * Extending the default errors to always give JSON errors
 *
 * @author Oliver Smith
 */

class MY_Exceptions extends CI_Exceptions
{
	function __construct()
	{
		parent::__construct();
	}

	/**
	 * 404 Page Not Found Handler
	 *
	 * @param	string	the page
	 * @param 	bool	log error yes/no
	 * @return	string
	 */
	function show_404($page = '', $log_error = TRUE)
	{
		// By default we log this, but allow a dev to skip it

		if ($log_error)
		{
			log_message('error', '404 Page Not Found --> '.$page);
		}

		header('Cache-Control: no-cache, must-revalidate');
		header('Content-type: application/json');
		header('HTTP/1.1 404 Not Found');

		echo json_encode(
			array(
				'status' => FALSE,
				'error' => 'Unknown method',
			)
		);

		exit;
	}

	/**
	 * General Error Page
	 *
	 * This function takes an error message as input
	 * (either as a string or an array) and displays
	 * it using the specified template.
	 *
	 * @access	private
	 * @param	string	the heading
	 * @param	string	the message
	 * @param	string	the template name
	 * @param 	int		the status code
	 * @return	string
	 */
	function show_error($heading, $message, $template = 'error_general', $status_code = 500)
	{
		header('Cache-Control: no-cache, must-revalidate');
		header('Content-type: application/json');
		header('HTTP/1.1 500 Internal Server Error');

		echo json_encode(
			array(
				'status' => FALSE,
				'error' => 'Internal Server Error',
			)
		);

		exit;
	}

	/**
	 * Native PHP error handler
	 *
	 * @access	private
	 * @param	string	the error severity
	 * @param	string	the error string
	 * @param	string	the error filepath
	 * @param	string	the error line number
	 * @return	string
	 */
	function show_php_error($severity, $message, $filepath, $line)
	{
		header('Cache-Control: no-cache, must-revalidate');
		header('Content-type: application/json');
		header('HTTP/1.1 500 Internal Server Error');

		echo json_encode(
			array(
				'status' => FALSE,
				'error' => 'Internal Server Error',
			)
		);

		exit;
	}
}

?>

Limitations

This code will only output a basic JSON formatted message, it will not vary the http error codes based on conditions, nor will it take into account accepts headers or similar. Right now this class meets my needs but features such as other formats could easily be added.