PHP异常处理程序杀死脚本

时间:2011-01-23 21:53:37

标签: php exception-handling

基本上我有一个自定义异常处理程序。当我处理异常时,我只是希望它回显消息并继续脚本。但是在我的方法处理异常后,脚本不会继续。

这是php的行为还是我的异常处理程序做错了什么?

4 个答案:

答案 0 :(得分:3)

这是php的一种行为。这与set_error_handler()的不同之处在于,根据set_exception_handler()上的手册,执行将在调用exception_handler后停止。 因此,请确保捕获所有异常,只允许那些想要的人杀死您的脚本。

这实际上是set_error_handler()在将所有错误转换为异常时与异常以及set_exception_handler()配对的原因...除非您实际上意味着您的应用程序严格编码以致任何通知或警告停止脚本。但至少它会让你跟踪一个涉及未设置数组键的调用。

答案 1 :(得分:2)

使用custom exception handler,,您需要在try / catch块中捕获异常,并在那里进行任何处理。

以下是The CodeUnit of Craig

中的示例
try {
    $error = 'Throw this error';
    throw new Exception($error);
    echo 'Never get here';
}
catch (Exception $e)
{
    echo 'Exception caught: ',  $e->getMessage(), "\n";
}

如果要捕获并打印任何未处理的异常,可以设置一个顶级异常处理程序,如this example from w3schools(near the bottom of the page)

<?php
 function myException($exception){
    echo "<b>Exception:</b> " , $exception->getMessage();
 }

 set_exception_handler('myException');

 throw new Exception('Uncaught Exception occurred');
?> 

应该打印:“例外:发生未捕获的异常”

答案 2 :(得分:0)

查看以下代码。它对我有用:

define(BR, "<br/>");
try {
   echo "throwing exception" . BR;
   throw new Exception("This is exception");
}
catch(Exception $ex) {
    echo "caught exception: " . BR . $ex->getMessage() . BR;

}
echo "Keep on going!. ..." . BR;

它打印以下内容:

throwing exception
caught exception: 
This is exception
Keep on going!. ...

你怎么说? 你能展示代码处理程序的代码吗?

答案 3 :(得分:0)

你可以这样做:

function handleError($errno, $errstring, $errfile, $errline, $errcontext) {
    if (error_reporting() & $errno) {
        // only process when included in error_reporting
        return processError($errno, $errstring);
    }
    return true;
}

function handleException($exception){
    // Here, you do whatever you want with the generated
    // exceptions. You can store them in a file or database,
    // output them in a debug section of your page or do
    // pretty much anything else with it, as if it's a
    // normal variable
}

function processError($code, $message){
    switch ($code) {
        case E_ERROR:
        case E_CORE_ERROR:
        case E_USER_ERROR:
            // Throw exception and stop execution of script
            throw new Exception($message, $code);
        default:
            // Execute exception handler and continue execution afterwards
            return handleException(new Exception($message, $code));
    }
}

// Set error handler to your custom handler
set_error_handler('handleError');
// Set exception handler to your custom handler
set_exception_handler('handleException');


// ---------------------------------- //

// Generate warning
processError(E_USER_WARNING, 'This went wrong, but we can continue');

// Generate fatal error :
processError(E_USER_ERROR, 'This went horrible wrong');

替代方法:

function handleError($errno, $errstring, $errfile, $errline, $errcontext) {
    if (error_reporting() & $errno) {
        // only process when included in error_reporting
        return handleException(new \Exception($errstring, $errno));
    }
    return true;
}

function handleException($exception){
    // Here, you do whatever you want with the generated
    // exceptions. You can store them in a file or database,
    // output them in a debug section of your page or do
    // pretty much anything else with it, as if it's a
    // normal variable

    switch ($code) {
        case E_ERROR:
        case E_CORE_ERROR:
        case E_USER_ERROR:
            // Make sure script exits here
            exit(1);
        default:
            // Let script continue
            return true;
    }
}

// Set error handler to your custom handler
set_error_handler('handleError');
// Set exception handler to your custom handler
set_exception_handler('handleException');


// ---------------------------------- //

// Generate warning
trigger_error('This went wrong, but we can continue', E_USER_WARNING);

// Generate fatal error :
trigger_error('This went horrible wrong', E_USER_ERROR);

后一种策略的一个优点是,如果您在函数$errcontext中执行$exception->getTrace(),则会获得handleException参数。

这对于某些调试目的非常有用。遗憾的是,只有在您的上下文中直接使用trigger_error时,这才有效,这意味着您无法使用包装函数/方法对trigger_error函数进行别名(因此您无法做到)如果您想要跟踪中的上下文数据,请使用function debug($code, $message) { return trigger_error($message, $code); }之类的内容。


修改

我找到dirty问题的一个trigger_error解决方法。

请考虑以下代码:

define("__DEBUG__", "Use of undefined constant DEBUG - assumed 'DEBUG'");

public static function handleError($code, $message, $file, $line, $context = false) {
    if ($message == __DEBUG__) {
        return static::exception(new \Exception(__DEBUG__, E_USER_WARNING));
    } else {
        if (error_reporting() & $code) {
            return static::exception(new \Exception($message, $code));
        }
        return true;
    }
}

public static function handleException($e) {
    global $debug;
    $code = $e->getCode();
    $trace = $e->getTrace();
    if ($e->getMessage() == __DEBUG__) {
        // DEBUG
        array_push($debug, array(
            '__TIME__' => microtime(),
            '__CONTEXT__' => array(
                'file' => $trace[0]['file'],
                'line' => $trace[0]['line'],
                'function' => $trace[1]['function'],
                'class' => $trace[1]['class'],
                'type' => $trace[1]['type'],
                'args' => $trace[0]['args'][4]
            )
        ));
    } else {
       // NORMAL ERROR HANDLING
    }
    return true;
}

使用此代码,您可以使用语句DEBUG;生成所有可用变量的列表以及任何特定上下文的堆栈跟踪。此列表存储在全局变量$debug中。您可以将其添加到日志文件,将其添加到数据库或打印出来。

这是一个非常非常肮脏的黑客,所以请自行决定使用它。但是,它可以使调试更容易,并允许您为调试代码创建一个干净的UI。