Error/Exception Handling
Kohana provides both an exception handler and an error handler that transforms errors into exceptions using PHP's ErrorException class. Many details of the error and the internal state of the application is displayed by the handler:
- Exception class
- Error level
- Error message
- Source of the error, with the error line highlighted
- A debug backtrace of the execution flow
- Included files, loaded extensions, and global variables
Example
Click any of the links to toggle the display of additional information:
ErrorException [ Notice ]:
MODPATH/userguide/views/userguide/examples/error.php [ 4 ]
1 <?php
2
3 // Should trigger an ErrorException with an E_NOTICE level
4 echo $var_does_not_exist;
5
6 ?> -
MODPATH/userguide/views/userguide/examples/error.php [ 4 ] » Kohana_Core::error_handler(arguments)
0integer 8
1string(38) "Undefined variable: var_does_not_exist"2string(72) "/var/www/guides/3.0/modules/userguide/views/userguide/examples/error.php"3integer 4
4array(2) ( "kohana_view_filename" => string(72) "/var/www/guides/3.0/modules/userguide/views/userguide/examples/error.php" "kohana_view_data" => array(0) )
1 <?php 2 3 // Should trigger an ErrorException with an E_NOTICE level 4 echo $var_does_not_exist; 5 6 ?> -
SYSPATH/classes/kohana/view.php [ 61 ] » include(arguments)
0string(52) "MODPATH/userguide/views/userguide/examples/error.php"56 ob_start(); 57 58 try 59 { 60 // Load the view within the current scope 61 include $kohana_view_filename; 62 } 63 catch (Exception $e) 64 { 65 // Delete the output buffer 66 ob_end_clean(); -
SYSPATH/classes/kohana/view.php [ 343 ] » Kohana_View::capture(arguments)
0string(72) "/var/www/guides/3.0/modules/userguide/views/userguide/examples/error.php"1array(0)338 { 339 throw new Kohana_View_Exception('You must set the file to use within your view before rendering'); 340 } 341 342 // Combine local and global data and capture the output 343 return View::capture($this->_file, $this->_data); 344 } 345 346 } // End View -
MODPATH/userguide/classes/kohana/kodoc/markdown.php [ 157 ] » Kohana_View->render()
152 { 153 list($search, $view) = $set; 154 155 try 156 { 157 $replace[$search] = View::factory($view)->render(); 158 } 159 catch (Exception $e) 160 { 161 ob_start(); 162 -
MODPATH/userguide/vendor/markdown/markdown.php [ 330 ] » Kohana_Kodoc_Markdown->doIncludeViews(arguments)
0string(4383) "<h1 id="errorexception-handling">Error/Exception Handling</h1> <p>Kohana provides both an exception handler and an error handle …"325 # contorted like /[ ]*\n+/ . 326 $text = preg_replace('/^[ ]+$/m', '', $text); 327 328 # Run document gamut methods. 329 foreach ($this->document_gamut as $method => $priority) { 330 $text = $this->$method($text); 331 } 332 333 $this->teardown(); 334 335 return $text . "\n"; -
MODPATH/userguide/vendor/markdown/markdown.php [ 64 ] » Markdown_Parser->transform(arguments)
0string(3676) "# Error/Exception Handling Kohana provides both an exception handler and an error handler that transforms errors into exception …"59 $parser_class = MARKDOWN_PARSER_CLASS; 60 $parser = new $parser_class; 61 } 62 63 # Transform text using parser. 64 return $parser->transform($text); 65 } 66 67 68 ### WordPress Plugin Interface ### 69 -
MODPATH/userguide/classes/controller/userguide.php [ 159 ] » Markdown(arguments)
textstring(3676) "# Error/Exception Handling Kohana provides both an exception handler and an error handler that transforms errors into exception …"154 // Set the page title 155 $this->template->title = $page == 'index' ? Kohana::config('userguide.modules.'.$module.'.name') : $this->title($page); 156 157 // Parse the page contents into the template 158 Kodoc_Markdown::$show_toc = true; 159 $this->template->content = Markdown(file_get_contents($file)); 160 Kodoc_Markdown::$show_toc = false; 161 162 // Attach this module's menu to the template 163 $this->template->menu = Markdown($this->_get_all_menu_markdown()); 164 -
{PHP internal call} » Controller_Userguide->action_docs(arguments)
0string(6) "kohana"1string(6) "errors" -
SYSPATH/classes/kohana/request.php [ 1217 ] » ReflectionMethod->invokeArgs(arguments)
0object Controller_Userguide(6)
{ public template => object View(2){ protected _file => string(66) "/var/www/guides/3.0/modules/userguide/views/userguide/template.php" protected _data => array(1) ( "title" => string(14) "Error Handling" ) }protected media => object Route(4){ protected _uri => string(20) "guide/media(/<file>)" protected _regex => array(1) ( "file" => string(2) ".+" ) protected _defaults => array(3) ( "controller" => string(9) "userguide" "action" => string(5) "media" "file" => NULL ) protected _route_regex => string(35) "#^guide/media(?:/(?P<file>.+))?$#uD" }protected api => NULL protected guide => object Route(4){ protected _uri => string(25) "guide(/<module>(/<page>))" protected _regex => array(1) ( "page" => string(2) ".+" ) protected _defaults => array(3) ( "controller" => string(9) "userguide" "action" => string(4) "docs" "module" => string(0) "" ) protected _route_regex => string(59) "#^guide(?:/(?P<module>[^/.,;?\n]++)(?:/(?P<page>.+))?)?$#uD" }public auto_render => bool TRUE public request => object Request(9){ public route => object Route(4)}{ protected _uri => string(25) "guide(/<module>(/<page>))" protected _regex => array(1) ( "page" => string(2) ".+" ) protected _defaults => array(3) ( "controller" => string(9) "userguide" "action" => string(4) "docs" "module" => string(0) "" ) protected _route_regex => string(59) "#^guide(?:/(?P<module>[^/.,;?\n]++)(?:/(?P<page>.+))?)?$#uD" }public status => integer 200 public response => string(0) "" public headers => array(1) ( "Content-Type" => string(24) "text/html; charset=utf-8" ) public directory => string(0) "" public controller => string(9) "userguide" public action => string(4) "docs" public uri => string(19) "guide/kohana/errors" protected _params => array(2) ( "module" => string(6) "kohana" "page" => string(6) "errors" ) }1array(2) ( "module" => string(6) "kohana" "page" => string(6) "errors" )
1212 1213 // Determine the action to use 1214 $action = empty($this->action) ? Route::$default_action : $this->action; 1215 1216 // Execute the main action with the parameters 1217 $class->getMethod('action_'.$action)->invokeArgs($controller, $this->_params); 1218 1219 // Execute the "after action" method 1220 $class->getMethod('after')->invoke($controller); 1221 } 1222 catch (Exception $e) -
/var/www/guides/3.0-bootstrap.php [ 108 ] » Kohana_Request->execute()
103 /** 104 * Execute the main request. A source of the URI can be passed, eg: $_SERVER['PATH_INFO']. 105 * If no source is specified, the URI will be automatically detected. 106 */ 107 echo Request::instance() 108 ->execute() 109 ->send_headers() 110 ->response; 111 } -
DOCROOT/3.0-index.php [ 109 ] » require(arguments)
0string(33) "/var/www/guides/3.0-bootstrap.php"104 // Load empty core extension 105 require SYSPATH.'classes/kohana'.EXT; 106 } 107 108 // Bootstrap the application 109 require '../guides/3.0-bootstrap'.EXT;
Environment
Included files (58)
DOCROOT/3.0-index.php |
SYSPATH/base.php |
SYSPATH/classes/kohana/core.php |
SYSPATH/classes/kohana.php |
/var/www/guides/3.0-bootstrap.php |
SYSPATH/classes/kohana/log.php |
SYSPATH/classes/kohana/config.php |
SYSPATH/classes/kohana/log/file.php |
SYSPATH/classes/kohana/log/writer.php |
SYSPATH/classes/kohana/config/file.php |
SYSPATH/classes/kohana/config/reader.php |
MODPATH/codebench/init.php |
SYSPATH/classes/route.php |
SYSPATH/classes/kohana/route.php |
MODPATH/userguide/init.php |
SYSPATH/classes/arr.php |
SYSPATH/classes/kohana/arr.php |
SYSPATH/config/userguide.php |
MODPATH/userguide/config/userguide.php |
MODPATH/pagination/config/userguide.php |
MODPATH/oauth/config/userguide.php |
MODPATH/orm/config/userguide.php |
MODPATH/image/config/userguide.php |
MODPATH/database/config/userguide.php |
MODPATH/codebench/config/userguide.php |
MODPATH/cache/config/userguide.php |
MODPATH/auth/config/userguide.php |
SYSPATH/classes/request.php |
SYSPATH/classes/kohana/request.php |
SYSPATH/classes/profiler.php |
SYSPATH/classes/kohana/profiler.php |
MODPATH/userguide/classes/controller/userguide.php |
SYSPATH/classes/controller/template.php |
SYSPATH/classes/kohana/controller/template.php |
SYSPATH/classes/controller.php |
SYSPATH/classes/kohana/controller.php |
MODPATH/userguide/vendor/markdown/markdown.php |
MODPATH/userguide/classes/kodoc/markdown.php |
MODPATH/userguide/classes/kohana/kodoc/markdown.php |
SYSPATH/classes/url.php |
SYSPATH/classes/kohana/url.php |
SYSPATH/classes/utf8.php |
SYSPATH/classes/kohana/utf8.php |
SYSPATH/classes/view.php |
SYSPATH/classes/kohana/view.php |
SYSPATH/utf8/transliterate_to_ascii.php |
MODPATH/userguide/classes/kodoc.php |
MODPATH/userguide/classes/kohana/kodoc.php |
SYSPATH/classes/html.php |
SYSPATH/classes/kohana/html.php |
MODPATH/userguide/views/userguide/examples/error.php |
SYSPATH/classes/date.php |
SYSPATH/classes/kohana/date.php |
SYSPATH/views/kohana/error.php |
SYSPATH/classes/i18n.php |
SYSPATH/classes/kohana/i18n.php |
SYSPATH/utf8/strlen.php |
SYSPATH/utf8/substr.php |
Loaded extensions (31)
Core |
date |
ereg |
libxml |
openssl |
pcre |
sqlite3 |
zlib |
ctype |
dom |
fileinfo |
filter |
hash |
iconv |
json |
SPL |
PDO |
pdo_sqlite |
session |
posix |
Reflection |
standard |
SimpleXML |
SQLite |
Phar |
tokenizer |
xml |
xmlreader |
xmlwriter |
cgi-fcgi |
curl |
$_COOKIE
$_SERVER
USER |
string(25) "u4ed3ba8b48afd82df60007bb" |
HOME |
string(31) "/home/u4ed3ba8b48afd82df60007bb" |
FCGI_ROLE |
string(9) "RESPONDER" |
REDIRECT_REDIRECT_UNIQUE_ID |
string(24) "Ty04eKwQCKYAADOwQGYAAAAA" |
REDIRECT_REDIRECT_SCRIPT_URL |
string(24) "/3.0/guide/kohana/errors" |
REDIRECT_REDIRECT_SCRIPT_URI |
string(50) "http://kohanaframework.org/3.0/guide/kohana/errors" |
REDIRECT_REDIRECT_HTTP_AUTHORIZATION |
string(0) "" |
REDIRECT_REDIRECT_CACHE2_HOST |
string(20) "tunnel.pagodabox.com" |
REDIRECT_REDIRECT_CACHE2_PORT |
string(5) "11211" |
REDIRECT_REDIRECT_STATUS |
string(3) "200" |
REDIRECT_UNIQUE_ID |
string(24) "Ty04eKwQCKYAADOwQGYAAAAA" |
REDIRECT_SCRIPT_URL |
string(24) "/3.0/guide/kohana/errors" |
REDIRECT_SCRIPT_URI |
string(50) "http://kohanaframework.org/3.0/guide/kohana/errors" |
REDIRECT_HTTP_AUTHORIZATION |
string(0) "" |
REDIRECT_CACHE2_HOST |
string(20) "tunnel.pagodabox.com" |
REDIRECT_CACHE2_PORT |
string(5) "11211" |
REDIRECT_HANDLER |
string(11) "php-fastcgi" |
REDIRECT_STATUS |
string(3) "200" |
UNIQUE_ID |
string(24) "Ty04eKwQCKYAADOwQGYAAAAA" |
SCRIPT_URL |
string(24) "/3.0/guide/kohana/errors" |
SCRIPT_URI |
string(50) "http://kohanaframework.org/3.0/guide/kohana/errors" |
HTTP_AUTHORIZATION |
string(0) "" |
CACHE2_HOST |
string(20) "tunnel.pagodabox.com" |
CACHE2_PORT |
string(5) "11211" |
HTTP_HOST |
string(19) "kohanaframework.org" |
HTTP_ACCEPT_ENCODING |
string(4) "gzip" |
HTTP_CF_CONNECTING_IP |
string(14) "38.107.179.232" |
HTTP_CF_IPCOUNTRY |
string(2) "US" |
HTTP_X_FORWARDED_FOR |
string(14) "38.107.179.232" |
HTTP_CF_VISITOR |
string(17) "{"scheme":"http"}" |
HTTP_X_CC_ID |
string(8) "ccc03-02" |
HTTP_USER_AGENT |
string(48) "CCBot/1.0 (+http://www.commoncrawl.org/bot.html)" |
HTTP_ACCEPT |
string(83) "text/html,application/xhtml+xml,text/xml;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5" |
HTTP_ACCEPT_LANGUAGE |
string(14) "en-us,en;q=0.5" |
HTTP_ACCEPT_CHARSET |
string(30) "ISO-8859-1,utf-8;q=0.7,*;q=0.7" |
HTTP_CACHE_CONTROL |
string(8) "no-cache" |
HTTP_PRAGMA |
string(8) "no-cache" |
HTTP_COOKIE |
string(52) "__cfduid=d3dbb6b01843f99da066304f0fa7adae31328360702" |
HTTP_X_FORWARDED_PROTO |
string(4) "http" |
HTTP_CONNECTION |
string(5) "close" |
PATH |
string(87) "/usr/local/nvm/v0.4.12/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/sbin:/sbin:/bin" |
SERVER_SIGNATURE |
string(0) "" |
SERVER_SOFTWARE |
string(20) "Apache/2.2.20 (Unix)" |
SERVER_NAME |
string(19) "kohanaframework.org" |
SERVER_ADDR |
string(12) "172.16.8.166" |
SERVER_PORT |
string(2) "80" |
REMOTE_ADDR |
string(9) "10.60.5.8" |
DOCUMENT_ROOT |
string(16) "/var/www/public/" |
SERVER_ADMIN |
string(21) "[email protected]" |
SCRIPT_FILENAME |
string(29) "/var/www/public/3.0-index.php" |
REMOTE_PORT |
string(5) "49609" |
REDIRECT_URL |
string(34) "/3.0-index.php/guide/kohana/errors" |
GATEWAY_INTERFACE |
string(7) "CGI/1.1" |
SERVER_PROTOCOL |
string(8) "HTTP/1.1" |
REQUEST_METHOD |
string(3) "GET" |
QUERY_STRING |
string(0) "" |
REQUEST_URI |
string(24) "/3.0/guide/kohana/errors" |
SCRIPT_NAME |
string(14) "/3.0-index.php" |
PATH_INFO |
string(20) "/guide/kohana/errors" |
PATH_TRANSLATED |
string(35) "/var/www/public/guide/kohana/errors" |
ORIG_PATH_INFO |
string(34) "/3.0-index.php/guide/kohana/errors" |
ORIG_SCRIPT_NAME |
string(16) "/cgi-bin/php-cgi" |
ORIG_SCRIPT_FILENAME |
string(20) "/usr/cgi-bin/php-cgi" |
ORIG_PATH_TRANSLATED |
string(49) "/var/www/public/3.0-index.php/guide/kohana/errors" |
PHP_SELF |
string(34) "/3.0-index.php/guide/kohana/errors" |
REQUEST_TIME |
integer 1328363640 |
Disabling Error/Exception Handling
If you do not want to use the internal error handling, you can disable it when calling Kohana::init:
Kohana::init(array('errors' => FALSE));
Error Reporting
By default, Kohana displays all errors, including strict mode warnings. This is set using error_reporting:
error_reporting(E_ALL | E_STRICT);
When you application is live and in production, a more conservative setting is recommended, such as ignoring notices:
error_reporting(E_ALL & ~E_NOTICE);
If you get a white screen when an error is triggered, your host probably has disabled displaying errors. You can turn it on again by adding this line just after your error_reporting call:
ini_set('display_errors', TRUE);
Errors should always be displayed, even in production, because it allows you to use exception and error handling to serve a nice error page rather than a blank white screen when an error happens.
Last thoughts
In production, your application should never have any uncaught exceptions, as this can expose sensitive information (via the stack trace). In the previous example we make the assumption that there is actually a view called 'views/errors/404', which is fairly safe to assume. One solution is to turn 'errors' off in Kohana::init for your production machine, so it displays the normal php errors rather than a stack trace.
// snippet from bootstrap.php
Kohana::init(array('
...
'errors' => false,
));
So rather than displaying the Kohana error page with the stack trace, it will display the default php error. Something like:
Fatal error: Uncaught Kohana_View_Exception [ 0 ]: The requested view errors/404 could not be found ~ SYSPATH/classes/kohana/view.php [ 215 ] thrown in /var/www/kohanut/docs.kohanaphp.com/3.0/system/classes/kohana/view.php on line 215
Keep in mind what I said earlier though: your application should never have any uncaught exceptions, so this should not be necesarry, though it is a good idea, simply because stack traces on a production environment are a very bad idea.
Another solution is to always have a catch statement that can't fail, something like an echo and an exit or a die(). This should almost never be necesarry, but it makes some people feel better at night. You can either wrap your entire bootstrap in a try catch, or simply wrap the contents of the catch in another try catch. For example:
try
{
// Execute the main request
$request->execute();
}
catch (Exception $e)
{
try
{
// Be sure to log the error
Kohana::$log->add(Kohana::ERROR, Kohana::exception_text($e));
// If there was an error, send a 404 response and display an error
$request->status = 404;
$request->response = View::factory('errors/404');
}
catch
{
// This is completely overkill, but helps some people sleep at night
echo "Something went terribly wrong. Try again in a few minutes.";
exit;
}
}