By default Kohana 3 doesn't have a method to display friendly error pages like that seen in Kohana 2; In this short guide you will learn how it is done.
You will need 'errors' => TRUE
passed to Kohana::init
. This will convert PHP
errors into exceptions which are easier to handle.
Our custom exception handler is self explanatory.
class Kohana_Exception extends Kohana_Kohana_Exception {
public static function handler(Exception $e)
{
if (Kohana::$environment === Kohana::DEVELOPMENT)
{
parent::handler($e);
}
else
{
try
{
Kohana::$log->add(Log::ERROR, parent::text($e));
$params = array
(
'action' => 500,
'message' => rawurlencode($e->getMessage())
);
if ($e instanceof HTTP_Exception)
{
$params['action'] = $e->getCode();
}
// Error sub-request.
echo Request::factory(Route::get('error')->uri($params))
->execute()
->send_headers()
->body();
}
catch (Exception $e)
{
// Clean the output buffer if one exists
ob_get_level() and ob_clean();
// Display the exception text
echo parent::text($e);
// Exit with an error status
exit(1);
}
}
}
}
If we are in the development environment then pass it off to Kohana otherwise:
HTTP_Exception
was thrown, then override the action with the error code.The action will be used as the HTTP response code. By default this is: 500 (internal
server error) unless a HTTP_Response_Exception
was thrown.
So this:
throw new HTTP_Exception_404(':file does not exist', array(':file' => 'Gaia'));
would display a nice 404 error page, where:
throw new Kohana_Exception('Directory :dir must be writable',
array(':dir' => Debug::path(Kohana::$cache_dir)));
would display an error 500 page.
The Route
Route::set('error', 'error/<action>(/<message>)', array('action' => '[0-9]++', 'message' => '.+'))
->defaults(array(
'controller' => 'error_handler'
));
public function before()
{
parent::before();
$this->template->page = URL::site(rawurldecode(Request::initial()->uri()));
// Internal request only!
if ( ! Request::current()->is_initial())
{
if ($message = rawurldecode($this->request->param('message')))
{
$this->template->message = $message;
}
}
else
{
$this->request->action(404);
}
$this->response->status((int) $this->request->action());
}
Otherwise use the 404 action. Users could otherwise craft their own error messages, eg:
error/404/email%20your%20login%20information%20to%20hacker%40google.com
public function action_404()
{
$this->template->title = '404 Not Found';
// Here we check to see if a 404 came from our website. This allows the
// webmaster to find broken links and update them in a shorter amount of time.
if (isset ($_SERVER['HTTP_REFERER']) AND strstr($_SERVER['HTTP_REFERER'], $_SERVER['SERVER_NAME']) !== FALSE)
{
// Set a local flag so we can display different messages in our template.
$this->template->local = TRUE;
}
// HTTP Status code.
$this->response->status(404);
}
public function action_503()
{
$this->template->title = 'Maintenance Mode';
}
public function action_500()
{
$this->template->title = 'Internal Server Error';
}
You will notice that each example method is named after the HTTP response code and sets the request response code.
So that's it. Now displaying a nice error page is as easy as:
throw new HTTP_Exception_503('The website is down');