将错误转换为异常:设计缺陷?

时间:2010-08-06 16:38:21

标签: php exception exception-handling interface error-handling

我最近遇到了一些使用自定义错误处理程序将任何PHP错误转换为通用应用程序异常的代码。还定义了一个自定义异常处理程序,如果异常位于特定的错误代码范围内,它将记录该异常。例如:

class AppException extends Exception
{

}

function error_handler($errno, $errstr, $errfile, $errline)
{
    throw new AppException($errstr, $errno);
}

function exception_handler($exception)
{
    $min = ...;
    $max = ...;

    if ($exception->getCode() >= $min && $exception->getCode() <= $max)
    {
        // log exception
    }
}

set_error_handler('error_handler');
set_exception_handler('exception_handler');

$a[1]; // throws exception

问题在于我看到了以下内容:

try
{
    do_something();
}
catch (AppException $exception)
{
}

这意味着实际编程错误与“异常”行为之间没有区别。在进一步挖掘之后,我发现了围绕PHP错误代表“异常”行为的想法设计的部分代码,例如:

...

function my_function($param1, $param2)
{
    // do something great
}

try
{
    my_function('only_one_param');
}
catch (AppException $exception)
{
}

最终会混淆错误和应用程序界面的设计。

您对以这种方式处理错误有何看法?是否值得将PHP的原生错误转化为异常?在上述代码库是围绕这个想法设计的情况下你做了什么?

3 个答案:

答案 0 :(得分:16)

就个人而言,我一直这样做。唯一的区别是,在我的error_handler函数中,我首先检查错误是否为E_NOTICE,如果不是,则仅抛出(我仍然记录通知)...

我会将AppException更改为扩展ErrorException的内容...类似于:PhpRuntimeErrorException extends ErrorException,您只能用于PHP错误......原因是它更具可读性(更容易分辨PhpRuntimeErrorException是什么而不需要弄清楚它被抛出的位置)。另一个原因是ErrorException将存储生成行/文件/ etc信息,它不会存储在别处(因为回溯从throw行开始)...

那么,你可以“尝试”这样的代码:

try {
    $f = fopen('foo.bar', 'r');
    $ret = '';
    while ($data = fread($f)) {
        $ret .= process($data);
    }
    fclose($f);
    return '';
} catch (PHPRuntimeErrorException $e) {
    throw new RuntimeException('Could not open file');
} catch (ProcessException $e) {
    fclose($f);
    throw new RuntimeException('Could not process data');
}
return $ret;

我还使我的默认异常处理程序生成500服务器错误页面。那是因为应该捕获任何异常,如果不是,那真的是服务器错误......

只是我的经验和意见......

答案 1 :(得分:5)

在PHP社区中存在一些争论。我相信一般的想法是错误是内部PHP函数抛出的东西,并且是你真正需要解决的编码问题;而异常是您的应用程序代码抛出的东西,您可能只需要“处理”。

然而,一些较新的SPL扩展(往往更加面向对象)确实使用了以前可能抛出错误的异常,因此存在一些灰色区域。

还有一个PHP核心类ErrorException - http://www.php.net/manual/en/class.errorexception.php,它看起来比你的代码示例更容易使用,如果这是你想要关闭的路线。

答案 2 :(得分:1)

我将所有内容,包括通知转换为异常。没有理由允许异常正常继续。未定义的变量或偏移量?这是一个问题。

https://github.com/KyleWolfe/PHPErrorNet