1

这是用 PHP 编写的,但它实际上与语言无关。

try
{
    try
    {
        $issue = new DM_Issue($core->db->escape_string($_GET['issue']));
    }
    catch(DM_Exception $e)
    {
        throw new Error_Page($tpl, ERR_NOT_FOUND, $e->getMessage());
    }
}
catch(Error_Page $e)
{
    die($e);
}

嵌套的 try, catch 块是一个很好的做法吗?仅对于错误页面来说似乎有点笨重 - 但是如果发生错误,我的 Issue Datamanager 会抛出异常,我认为这是检测错误的好方法。

Error_Page 异常只是一个错误页面编译器。

我可能只是迂腐,但你认为这是报告错误的好方法吗?如果是,你能建议一个更好的方法来写这个吗?

谢谢

4

7 回答 7

9

您正在为页面逻辑使用异常,我个人认为这不是一件好事。异常应该用于在发生不良或意外事情时发出信号,而不是控制错误页面的输出。如果要基于异常生成错误页面,请考虑使用set_exception_handler。任何未捕获的异常都通过您指定的任何回调方法运行。请记住,这并不能阻止异常的“致命性”。在通过回调传递异常后,执行将在任何未捕获的异常后正常停止。

于 2008-09-19T16:50:35.970 回答
2

我认为你最好不要嵌套。如果您期望多种异常类型,请使用多个捕获。

try{
  Something();
}
catch( SpecificException se )
{blah();}
catch( AnotherException ae )
{blah();}
于 2008-09-19T16:48:59.267 回答
2

理想的情况是在可以处理它们的级别捕获异常。不是之前(浪费时间),也不是之后(你失去了上下文)。

因此,如果 $tpl 和 ERR_NOT_FOUND 是仅在新的 DM_Issue 调用附近“已知”的信息,例如因为在其他地方创建 DM_Issue 并且需要 ERR_SOMETHING_ELSE,或者因为 $tpl 的值不同,那么你'在正确的地方捕获第一个异常。

如何从那个地方走向死亡是另一个问题。另一种选择是死在那里。但是如果你这样做了,那么干预代码就没有机会在错误之后但退出之前做任何事情(例如以某种方式清除某些内容或修改错误页面)。有明确的控制流也很好。所以我觉得你很好。

我假设您的示例不是一个完整的应用程序 - 如果是,那么它可能是不必要的冗长,您可能会死在 DM_Exception catch 子句中。但是对于一个真正的应用程序,我赞成不只是死在茫茫荒野中的原则。

于 2008-09-19T16:59:09.600 回答
0

根据您的需要,这可能很好,但我通常很犹豫要捕获异常,将消息包装在新异常中,然后重新抛出它,因为您在包装中丢失了原始异常中的堆栈跟踪(以及可能的其他)信息例外。如果您确定在检查包装异常时不需要该信息,那么它可能没问题。

于 2008-09-19T16:49:32.227 回答
0

我不确定 PHP,但在例如 C# 中,您可以拥有多个 catch-Block,因此不需要嵌套的 try/catch-combinations。

一般来说,我认为使用 try/catch/finally 进行错误处理始终是常识,也用于“仅”显示错误页面。这是一种处理错误并避免崩溃时出现奇怪行为的干净方法。

于 2008-09-19T16:51:28.697 回答
0

我不会在未找到的问题上抛出异常 - 这是应用程序的有效状态,您不需要堆栈跟踪来显示 404。

你需要捕捉的是意外的失败,比如 sql 错误——这时异常处理就派上用场了。我会将您的代码更改为如下所示:

try {
    $issue = DM_Issue::fetch($core->db->escape_string($_GET['issue']));
}
catch (SQLException $e) {
    log_error('SQL Error: DM_Issue::fetch()', $e->get_message());
}
catch (Exception $e) {
    log_error('Exception: DM_Issue::fetch()', $e->get_message());
}

if(!$issue) {
    display_error_page($tpl, ERR_NOT_FOUND);
}
else
{
    // ... do stuff with $issue object.
}
于 2008-09-19T17:22:59.230 回答
0

仅当存在潜在的站点破坏事件时才应使用异常 - 例如数据库查询未正确执行或配置错误。一个很好的例子是 Apache 进程不可写缓存或日志目录。

这里的想法是,开发人员可以停止可能破坏整个站点的代码,以便您可以在部署之前修复它们。它们也是健全性检查,以确保如果环境发生变化(例如,有人更改缓存文件夹的权限或更改数据库方案),站点会在可能损坏任何东西之前停止。

所以不行; 嵌套的 catch 处理程序不是一个好主意。在我的页面中,我的 index.php 文件将其代码包装在一个 try...cache 块中——如果发生不好的事情,它会检查它是否在生产中;或者给我发电子邮件并显示一个通用的错误页面,或者在屏幕上显示错误。

请记住:PHP 不是 C#。C#(除了 ASP.net 的例外(呵呵,没有双关语:p))用于包含状态的应用程序 - 而 PHP 是一种无状态脚本语言。

于 2008-09-20T00:16:30.220 回答