Yii 中的致命错误处理 [英] Fatal error handling in Yii

查看:30
本文介绍了Yii 中的致命错误处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有办法通过电子邮件/日志记录基于 Yii 框架的项目中发生的 php 致命错误?

Is there a way to email / log php fatal errors happening in the project based on Yii framework?

例如,可以将 Yii 配置为通过电子邮件发送未定义变量"错误,但致命错误只能通过单独的、未集成到框架代码中的方式进行监控,这并不理想.

For example it is possible to configure Yii to email "undefined variable" errors but fatal ones can only be monitored by a separate, non integrated into framework code which is not ideal.

推荐答案

在 php 中,可以使用 register_shutdown_function() 函数拦截致命错误.

In php it is possible to intercept fatal errors using register_shutdown_function() function.

首先,让我们添加早期"致命解析错误处理程序.它应该进入 index.php.这段代码的目的是捕捉那些在控制器启动之前可能发生的错误.由于我们正在捕获应用程序启动期间可能发生的错误,因此最好使用简单的 php 而不依赖任何外部库:

Firstly, lets add "early" fatal and parse error handler. It should go into index.php. The purpose of this code is to catch those errors that could happened before controller has been initiated. As we are catching errors which could occur during application initiation it is better to use simple php without reliance on any external libs:

// 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 错误处理程序或日志记录.首先,我们需要注册另一个关闭函数,它是我们基本控制器的一部分,可以使用 Yii 框架提供的标准错误处理和错误日志记录(这个想法和大部分代码都归功于vitalets @ http://habrahabr.ru/post/136138/)

At this stage we are still not using Yii error handler nor logging. To start we need to register another shutdown function which is part of our base controller and can use standard error handling AND error logging provided by Yii framework (credits for the idea and bigger part of the code goes to vitalets @ http://habrahabr.ru/post/136138/)

请注意,此函数将通知解析错误,只要它们不是实际控制器文件中的解析错误,而是模型、帮助程序、视图等外部文件中的解析错误.如果控制器中出现解析错误,则早期处理程序将处理它.

Note that this function will notify about parse errors as long as they are not parse errors in the actual controller files but in external files like models, helpers, views. If parse error is in controller early handler will deal with it.

此外,此功能允许呈现更好的错误页面,而不是转储致命错误文本或显示空白屏幕(如果 display_errors 关闭).

Also this function allows to render a nicer error page rather then dumping fatal error text or showing a blank screen (if display_errors is off).

/**
 * 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']);
        }
    }

    // ...
}

这篇关于Yii 中的致命错误处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆