有没有一种方法可以通过电子邮件发送/记录基于 Yii 框架的项目中发生的 php fatal error ?
例如,可以将 Yii 配置为通过电子邮件发送“ undefined variable ”错误,但 fatal error 只能由单独的、未集成到框架代码中的来监控,这并不理想。
最佳答案
在 php 中,可以使用 register_shutdown_function()
函数拦截 fatal error 。
首先,让我们添加“早期”fatal 和parse 错误处理程序。它应该进入 index.php。 此代码的目的是捕获那些在 Controller 启动之前可能发生的错误。由于我们正在捕获应用程序启动期间可能发生的错误,因此最好使用不依赖任何外部库的简单 php:
// Early fatal errors handler, it will be replaced by a full featured one in Controller class
// (given it does not have any parse or fatal errors of its own)
function earlyFatalErrorHandler($unregister = false)
{
// Functionality for "unregistering" shutdown function
static $unregistered;
if ($unregister) $unregistered = true;
if ($unregistered) return;
// 1. error_get_last() returns NULL if error handled via set_error_handler
// 2. error_get_last() returns error even if error_reporting level less then error
$error = error_get_last();
// Fatal errors
$errorsToHandle = E_ERROR | E_PARSE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING;
if ((!defined('APP_PRODUCTION_MODE') || APP_PRODUCTION_MODE) && !is_null($error) && ($error['type'] & $errorsToHandle))
{
$message = 'FATAL ERROR: ' . $error['message'];
if (!empty($error['file'])) $message .= ' (' . $error['file'] . ' :' . $error['line']. ')';
mail('errors@YOURDOMAIN.COM', $message, print_r($error, 1));
// Tell customer that you are aware of the issue and will take care of things
// echo "Apocalypse now!!!";
}
}
register_shutdown_function('earlyFatalErrorHandler');
在这个阶段,我们仍然没有使用 Yii 错误处理程序或日志记录。首先,我们需要注册另一个关闭函数,它是我们基本 Controller 的一部分,可以使用 Yii 框架提供的标准错误处理和错误日志记录(这个想法的功劳和大部分代码转到 vitalets @ http://habrahabr.ru/post/136138/ )
请注意,此函数将通知有关解析错误,只要它们不是实际 Controller 文件中的解析错误,而是模型、助手、 View 等外部文件中的解析错误。如果 Controller 中存在解析错误,则早期处理程序将对其进行处理。
此函数还允许呈现更好的错误页面,而不是转储 fatal error 文本或显示空白屏幕(如果 display_errors 关闭)。
/**
* Controller is the customized base controller class.
* All controller classes for this application should extend from this base class.
*/
class Controller extends CController
{
// ...
public function init()
{
register_shutdown_function(array($this, 'onShutdownHandler'));
earlyFatalErrorHandler(true); // Unregister early hanlder
}
public function onShutdownHandler()
{
// 1. error_get_last() returns NULL if error handled via set_error_handler
// 2. error_get_last() returns error even if error_reporting level less then error
$error = error_get_last();
// Fatal errors
$errorsToHandle = E_ERROR | E_PARSE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING;
if (!is_null($error) && ($error['type'] & $errorsToHandle))
{
// It's better to set errorAction = null to use system view "error.php" instead of
// run another controller/action (less possibility of additional errors)
Yii::app()->errorHandler->errorAction = null;
$message = 'FATAL ERROR: ' . $error['message'];
if (!empty($error['file'])) $message .= ' (' . $error['file'] . ' :' . $error['line']. ')';
// Force log & flush as logs were already processed as the error is fatal
Yii::log($message, CLogger::LEVEL_ERROR, 'php');
Yii::getLogger()->flush(true);
// Pass the error to Yii error handler (standard or a custom handler you may be using)
Yii::app()->handleError($error['type'], 'Fatal error: ' . $error['message'], $error['file'], $error['line']);
}
}
// ...
}
关于php - Yii 中的 fatal error 处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18177980/