Browse Source

Moved the fatal error detection to App::shutdown and keeping the fatal error handler cleaner. It helps to be extended by applications/plugins.

Juan Basso 14 years ago
parent
commit
1428659f88

+ 4 - 4
app/Config/core.php

@@ -41,20 +41,20 @@
  *
  * Options:
  *
+ * - `handleFatalError` - callback - The callback to handle fatal errors. You can set this to any
+ *    callback type, including anonymous functions.
  * - `handler` - callback - The callback to handle errors. You can set this to any callback type,
  *    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(
+		'handleFatalError' => 'ErrorHandler::handleFatalError',
 		'handler' => 'ErrorHandler::handleError',
 		'level' => E_ALL & ~E_DEPRECATED,
-		'trace' => true,
-		'handleFatalError' => true
+		'trace' => true
 	));
 
 /**

+ 3 - 0
lib/Cake/Console/Templates/skel/Config/core.php

@@ -41,6 +41,8 @@
  *
  * Options:
  *
+ * - `handleFatalError` - callback - The callback to handle fatal errors. You can set this to any
+ *    callback type, including anonymous functions.
  * - `handler` - callback - The callback to handle errors. You can set this to any callback type,
  *    including anonymous functions.
  * - `level` - int - The level of errors you are interested in capturing.
@@ -49,6 +51,7 @@
  * @see ErrorHandler for more information on error handling and configuration.
  */
 	Configure::write('Error', array(
+		'handleFatalError' => 'ErrorHandler::handleFatalError',
 		'handler' => 'ErrorHandler::handleError',
 		'level' => E_ALL & ~E_DEPRECATED,
 		'trace' => true

+ 27 - 1
lib/Cake/Core/App.php

@@ -881,7 +881,8 @@ class App {
 /**
  * Object destructor.
  *
- * Writes cache file if changes have been made to the $_map
+ * Writes cache file if changes have been made to the $_map. Also, check if a fatal
+ * error happened and call the handler.
  *
  * @return void
  */
@@ -892,6 +893,31 @@ class App {
 		if (self::$_objectCacheChange) {
 			Cache::write('object_map', self::$_objects, '_cake_core_');
 		}
+
+		self::_checkFatalError();
+	}
+
+/**
+ * Check if a fatal error happened and trigger the configured handler if configured
+ *
+ * @return void
+ */
+	protected static function _checkFatalError() {
+		$lastError = error_get_last();
+		if (!is_array($lastError)) {
+			return;
+		}
+
+		list(, $log) = ErrorHandler::mapErrorCode($lastError['type']);
+		if ($log !== LOG_ERROR) {
+			return;
+		}
+
+		$fatalErrorHandler = Configure::read('Error.handleFatalError');
+		if (!is_callable($fatalErrorHandler)) {
+			return;
+		}
+		call_user_func($fatalErrorHandler, $lastError);
 	}
 
 }

+ 0 - 1
lib/Cake/Core/Configure.php

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

+ 5 - 20
lib/Cake/Error/ErrorHandler.php

@@ -186,27 +186,12 @@ class ErrorHandler {
 /**
  * Generate an error page when some fatal error happens.
  *
- * Use Configure::write('Error.handleFatalError', false) to disable this feature
- *
+ * @param array $error Array with error information. See `error_get_last()` function
  * @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);
+	public static function handleFatalError($error) {
+		$logMessage = 'Fatal Error (' . $error['type'] . '): ' . $error['message'] . ' in [' . $error['file'] . ', line ' . $error['line'] . ']';
+		CakeLog::write(LOG_ERROR, $logMessage);
 
 		$exceptionHandler = Configure::read('Exception.handler');
 		if (!is_callable($exceptionHandler)) {
@@ -215,7 +200,7 @@ class ErrorHandler {
 
 		ob_clean();
 		if (Configure::read('debug')) {
-			call_user_func($exceptionHandler, new FatalErrorException($lastError['message'], 500, $lastError['file'], $lastError['line']));
+			call_user_func($exceptionHandler, new FatalErrorException($error['message'], 500, $error['file'], $error['line']));
 		} else {
 			call_user_func($exceptionHandler, new InternalErrorException());
 		}