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'
);