PHP异常处理程序终止脚本

PHP异常处理程序终止脚本,php,exception-handling,Php,Exception Handling,基本上我有一个自定义的异常处理程序。当我处理异常时,我只希望它回显消息并继续脚本。但是在我的方法处理异常之后,脚本就不会继续了 这是php的行为,还是我的异常处理程序做错了什么?有了a,您将希望在try/catch块中捕获异常,并在其中执行任何处理 下面是来自的示例 如果要捕获并打印任何未处理的异常,可以设置顶级异常处理程序,如 应打印:“异常:未捕获的异常发生”查看以下代码。这对我很有用: define(BR, "<br/>"); try { echo "throwing

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

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

有了a,您将希望在try/catch块中捕获异常,并在其中执行任何处理

下面是来自的示例

如果要捕获并打印任何未处理的异常,可以设置顶级异常处理程序,如



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

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

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;
你怎么说?
您能显示代码处理程序的代码吗?

这是php的一种行为。这与
set\u error\u handler()
的不同之处在于,根据上的手册,调用异常处理程序后,执行将停止。因此,请确保捕获所有异常,只允许那些希望终止脚本的异常通过

这就是为什么在将所有错误转换为异常时,
set\u error\u handler()
与异常和
set\u exception\u handler()
不能很好地匹配的原因。。。除非您的意思是您的应用程序的编码非常严格,以至于任何通知或警告都会停止脚本。但至少它会对涉及未设置数组键的调用进行跟踪。

您可以这样做:

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);
后一种策略的优点是,如果在函数
handleException
中执行
$exception->getTrace()
,则可以获得
$errcontext
参数

这对于某些调试目的非常有用。不幸的是,只有直接从上下文中使用
trigger\u error
时,这才有效,这意味着不能使用包装函数/方法来别名
trigger\u error
函数(因此不能执行
函数调试($code,$message){return trigger\u error($message,$code);}
如果要在跟踪中显示上下文数据)


编辑

我发现了一个
dirty
解决
trigger\u 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。

请参阅手册中的注释:当我在处理程序中得到一个未处理的EXECTION时,您不理解我的问题,我希望脚本显示一个错误消息,然后继续使用脚本修改我的答案,以显示一些示例代码,这些代码将打印任何未经处理的异常。我相信OP意味着使用
set_exception_handler()
函数创建一个通用catch,以完全替换某些try/catch块,同时具有继续脚本的相同效果。。。这是不可能的。@bob驱逐舰:我不知道你说的“OP”是什么意思。然而,我相信我编写的脚本解决了这个问题:每次执行一些您认为会杀死脚本的代码时,您都会用try/catch块将其包装起来,然后它会将是否杀死脚本的决定传递给您。如您所述,使用全局异常处理程序不会授予此权限。我说的对吗?“OP”是“原创海报”的缩写,还是问题的作者。“如您所述,使用全局异常处理程序不会授予此权限。我说的对吗?”这是正确的,但问题围绕着PHP故意未捕获异常的行为和异常处理程序函数。谢谢,我已经决定这样做,任何错误都会触发异常。这将使我的框架更加严格,但从长远来看,这是我认为最好的方式:D@Ozzy:我完全赞成将对不存在的数组键的回音视为可崩溃的攻击。只需确保允许在异常处理程序中包含可自定义的错误页面,这样,如果框架的用户犯了这样一个简单的错误,他们就会优雅地死去。另外,不要忘记“headers ready sent”问题,您的处理方法可能会终止页面的中间输出。即使打印一个导致错误页面的元重定向标签也不会起作用,如果输出在构建文本框的中间停止。
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);
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;
}