Added a handler for fatal errors, showing internal server error page when debug is disabled or a custom fatal error page when enabled.

This commit is contained in:
Juan Basso 2012-03-29 00:20:17 -04:00
parent f677bfea7d
commit 440f0c38eb
5 changed files with 105 additions and 1 deletions

View file

@ -45,13 +45,16 @@
* including anonymous functions.
* - `level` - int - The level of errors you are interested in capturing.
* - `trace` - boolean - Include stack traces for errors in log files.
* - `handleFatalError` - boolean - Enable the CakePHP fatal error handler, generating custom
* pages for fatal errors instead of show broke pages.
*
* @see ErrorHandler for more information on error handling and configuration.
*/
Configure::write('Error', array(
'handler' => 'ErrorHandler::handleError',
'level' => E_ALL & ~E_DEPRECATED,
'trace' => true
'trace' => true,
'handleFatalError' => true
));
/**

View file

@ -345,5 +345,6 @@ class Configure {
if (!empty($exception['handler'])) {
set_exception_handler($exception['handler']);
}
register_shutdown_function('ErrorHandler::handleFatalError');
}
}

View file

@ -183,6 +183,44 @@ class ErrorHandler {
}
}
/**
* Generate an error page when some fatal error happens.
*
* Use Configure::write('Error.handleFatalError', false) to disable this feature
*
* @return void
*/
public static function handleFatalError() {
if (Configure::read('Error.handleFatalError') !== true) {
return;
}
$lastError = error_get_last();
if (!is_array($lastError)) {
return;
}
list($error, $log) = self::mapErrorCode($lastError['type']);
if ($log !== LOG_ERROR) {
return;
}
$logMessage = $error . ' (' . $lastError['type'] . '): ' . $lastError['message'] . ' in [' . $lastError['file'] . ', line ' . $lastError['line'] . ']';
CakeLog::write($log, $logMessage);
$exceptionHandler = Configure::read('Exception.handler');
if (!is_callable($exceptionHandler)) {
return;
}
ob_clean();
if (Configure::read('debug')) {
call_user_func($exceptionHandler, new FatalErrorException($lastError['message'], 500, $lastError['file'], $lastError['line']));
} else {
call_user_func($exceptionHandler, new InternalErrorException());
}
}
/**
* Map an error code into an Error word, and log location.
*

View file

@ -517,3 +517,30 @@ class XmlException extends CakeException {
*/
class ConsoleException extends CakeException {
}
/**
* Represents a fatal error
*
* @package Cake.Error
*/
class FatalErrorException extends CakeException {
/**
* Constructor
*
* @param string $message
* @param integer $code
* @param string $file
* @param integer $line
*/
public function __construct($message, $code = 500, $file = null, $line = null) {
parent::__construct($message, $code);
if ($file) {
$this->file = $file;
}
if ($line) {
$this->line = $line;
}
}
}

View file

@ -0,0 +1,35 @@
<?php
/**
*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package Cake.View.Errors
* @since CakePHP(tm) v 2.2.0
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
?>
<h2><?php echo __d('cake_dev', 'Fatal Error'); ?></h2>
<p class="error">
<strong><?php echo __d('cake_dev', 'Error'); ?>: </strong>
<?php echo h($error->getMessage()); ?>
<br>
<strong><?php echo __d('cake_dev', 'File'); ?>: </strong>
<?php echo h($error->getFile()); ?>
<br>
<strong><?php echo __d('cake_dev', 'Line'); ?>: </strong>
<?php echo h($error->getLine()); ?>
</p>
<p class="notice">
<strong><?php echo __d('cake_dev', 'Notice'); ?>: </strong>
<?php echo __d('cake_dev', 'If you want to customize this error message, create %s', APP_DIR . DS . 'View' . DS . 'Errors' . DS . 'fatal_error.ctp'); ?>
</p>