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

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

问题描述



例如,可以将Yii配置为发送电子邮件undefined可变错误,但致命的错误只能通过一个单独的,非集成的框架代码进行监视,这不是理想的。

解决方案

php可以使用 register_shutdown_function()函数拦截致命错误。



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

  /早期致命错误处理程序,它将被Controller类
//中的全功能代码(由于它没有自己的任何解析或致命错误)替换
函数earlyFatalErrorHandler($ unregister = false )
{
//取消注册关闭功能的功能
static $ unregistered;
if($ unregister)$ unregistered = true;
if($ unregistered)return;

// 1.如果error_get_last ();

//致命错误
$ errorsToHandle = E_ERROR | E_PARSE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING;

如果((!define('APP_PRODUCTION_MODE')|| APP_PRODUCTION_MODE)&!is_null($ error)&&($ error ['type']& $ errorsToHandle)
{
$ message ='致命错误:'。 $错误[消息];
if(!empty($ error ['file']))$ message。='('。$ error ['file']。':'。$ error ['line']。')';

mail('errors@YOURDOMAIN.COM',$ message,print_r($ error,1));

//告诉客户你知道这个问题,并且会照顾好事物
// echoApocalypse now !!!;
}
}

register_shutdown_function('earlyFatalErrorHandler');

在这个阶段我们还没有使用Yii错误处理程序和日志记录。要开始,我们需要注册另一个关闭功能,这是我们的基本控制器的一部分,可以使用Yii框架提供的标准错误处理和错误记录(这个想法的大部分代码来自于重要的部分@ http://habrahabr.ru/post/136138/



请注意,此功能将通知解析错误,只要它们不解析实际控制器文件中的错误,但在外部文件(如模型,帮助程序,视图)中。如果解析错误在控制器早期处理程序将处理它。



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

  / ** 
*控制器是自定义的基本控制器类。
*此应用程序的所有控制器类应从此基类扩展。
* /
class Controller extends CController
{
// ...

public function init()
{
register_shutdown_function(array($ this,'onShutdownHandler'));
earlyFatalErrorHandler(true); //取消注册早期hanlder
}

public function onShutdownHandler()
{
// 1.如果通过set_error_handler处理错误
,错误返回NULL // 2. error_get_last()返回错误,即使error_reporting级别少于错误
$ error = error_get_last();

//致命错误
$ errorsToHandle = E_ERROR | E_PARSE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING;

if(!is_null($ error)&&($ error ['type']& $ errorsToHandle))
{
//最好设置errorAction = null使用系统视图error.php而不是
//运行另一个控制器/操作(更少的可能性额外的错误)
Yii :: app() - > errorHandler-> errorAction =空值;

$ message ='致命错误:'。 $错误[消息];
if(!empty($ error ['file']))$ message。='('。$ error ['file']。':'。$ error ['line']。')';

//强制log&因为日志已经被处理,因为错误是致命的
Yii :: log($ message,CLogger :: LEVEL_ERROR,'php');
Yii :: getLogger() - > flush(true);

//将错误传递给Yii错误处理程序(标准或您可能正在使用的自定义处理程序)
Yii :: app() - > handleError($ error ['type'] ,'致命错误:'$ error ['message'],$ error ['file'],$ error ['line']);
}
}

// ...
}


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

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.

解决方案

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

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');

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.

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天全站免登陆