# Friendly Error Pages 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. ## Prerequisites You will need `'errors' => TRUE` passed to `Kohana::init`. This will convert PHP errors into exceptions which are easier to handle. ## 1. An Improved Exception Handler Our custom exception handler is self explanatory. class Kohana_Exception extends Kohana_Kohana_Exception { public static function handler(Exception $e) { if (Kohana::DEVELOPMENT === Kohana::$environment) { parent::handler($e); } else { try { Kohana::$log->add(Log::ERROR, parent::text($e)); $attributes = array ( 'action' => 500, 'message' => rawurlencode($e->getMessage()) ); if ($e instanceof HTTP_Exception) { $attributes['action'] = $e->getCode(); } // Error sub-request. echo Request::factory(Route::get('error')->uri($attributes)) ->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: * Log the error * Set the route action and message attributes. * If a `HTTP_Exception` was thrown, then override the action with the error code. * Fire off an internal sub-request. 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/(/)', array('action' => '[0-9]++', 'message' => '.+')) ->defaults(array( 'controller' => 'error_handler' )); ## 2. The Error Page Controller public function before() { parent::before(); $this->template->page = URL::site(rawurldecode(Request::$initial->uri())); // Internal request only! if (Request::$initial !== Request::$current) { if ($message = rawurldecode($this->request->param('message'))) { $this->template->message = $message; } } else { $this->request->action(404); } $this->response->status((int) $this->request->action()); } 1. Set a template variable "page" so the user can see what they requested. This is for display purposes only. 2. If an internal request, then set a template variable "message" to be shown to the user. 3. 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. ## 3. Conclusion So that's it. Now displaying a nice error page is as easy as: throw new HTTP_Exception_503('The website is down');