不停止执行的情况下抛出异常?

5
我在处理一个庞大的项目(数十万行代码),但其中存在许多MySQL错误。为了解决这个问题,我正在清理它们。我的所有查询都通过数据库类进行,所以我已经做的事是每当出现SQL错误时就抛出异常。问题在于我不能让程序停止执行。它必须像以前一样继续执行,并记录异常信息,以便我可以逐个修复它们。
我希望set_exception_handler能做到我想要的效果,但文档明确说明它会在调用我的处理程序后停止执行。那么我该如何解决呢?
异常可以阻止当前函数的执行,但然后我希望它退出该函数,可能返回null或false,然后像往常一样继续执行,但我需要它调用我的全局异常处理程序。
澄清一下:
我希望从我的数据库类中抛出异常(每当出现SQL错误时)。然后我想将此错误记录/显示在屏幕上,直到我可以修复SQL错误或在try/catch中包含有问题的语句。我不想让它停止执行。如果我只是调用某个error_handler()而不是抛出异常,则无法捕获它。如果我立即捕获它(也在DB类内部),则无法在堆栈下方再次捕获它(除非我重新抛出它,但这会导致程序停止执行)。

1
@downvoter:能否解释一下为什么这是一个不好的问题? - mpen
我不想听起来傲慢或者什么的,但是看起来你不熟悉异常处理的工作原理(从堆栈中剥离帧,丢失当前环境变量值等)。你想要做的就是像@pgraham在这里评论的那样添加一个调试打印 - 就像我在你发布并删除的答案上评论的那样。我认为你的问题会让其他人更加困惑而不是帮助他们。所以我选择了点踩。 - Nir Alfasi
1
@alfasin:1)我删除了我的帖子,因为在pgraham提出上面的问题后,我意识到它没有意义。2)问题本身并不是为了启发任何人,这就是为什么它是一个问题。如果你认为这是一个坏主意,请发表回答,以便它可以帮助他们。对于错误的信念而将一个问题投票下来可能会阻止其他人学习。3)我有调试打印。我想要异常,这样它们就可以被捕获(如上面的评论所解释的那样)。 - mpen
此外,它们应该是异常情况。SQL 错误就是错误,我的项目还没有达到可以随意崩溃的状态。我正在尝试通过创建一个临时解决方案来妥协,直到我能够完成清理错误。 - mpen
1
简短的回答是否定的。如果您无法将所有代码包装在try/catch块中,则到达顶级异常处理程序的任何内容都将死亡。我的建议是定义一个日志记录函数,您可以将异常传递给该函数。然后,在将MySQL错误转换为异常时,不要抛出异常,而是将其传递给日志记录函数。稍后,当您确实需要致命错误时,您只需要更新日志记录函数以同时抛出异常即可。 - pgraham
显示剩余3条评论
3个回答

1

如果我理解你的意思是:

function myFunction($params) {

    try {

        //your code which throws Exception

    } catch (Exception $e) {

        myErrorFunction($e);
        return false;
    }

}

不,我认为你没有完全理解我的要求。我应该在哪里放置try/catch?我现在没有时间将其放置在每个SQL查询周围,所以我必须将其放置在我抛出它的确切位置...但是然后我无法在更下面捕获它,因为我已经捕获了它。我不认为我想做的事情是可能的。 - mpen
你可以将整个代码或仅用于数据库类进行包装。你有多少个方法?10?20?只需使用try catch将它们包装起来,每次执行时例如 $db->myCustonQuery(),你知道如果发生错误,它将抛出一个异常,你可以在其他地方处理。这个答案的真正重点是,如果你return false,你将能够继续执行。 - Shoe
如果我整个代码都包含在 try-catch 块里,那么当出现异常时,执行会跳转到 catch 块;但实际上我需要它在抛出异常的地方继续执行。在我的数据库类中,大约有 10-20 种方法需要进行这样的封装,但这些封装也不能让我在想要的位置捕获异常。基本上,我希望能够在调用 $db->GetSingleRecord() 的位置捕获异常,但是由于此函数被调用了数千次,我必须遍历所有这些调用才能做到。这说得通吗?我认为我所要求的是不现实的,但这将是最理想的情况。 - mpen
除了时间限制之外,听起来你真的需要重构整个东西。 - Ingmar Boddington
@Ing:我很乐意。不过,时间限制是无法忽视的现实。 - mpen

0

我想我找到了一个解决方法。不是抛出异常,而是直接使用异常调用我的处理程序:

global_exception_handler(new MySqlException($error_message)); 

这样我的处理程序仍然会被调用,但执行会继续。

然后同样的异常处理程序仍然可以用来捕获所有其他实际抛出的异常:

function _global_exception_handler($e) {
    // log error here
}

set_exception_handler('global_exception_handler');

这有点像添加调试打印,不是吗? - Nir Alfasi

0

虽然这是一篇旧帖子,但我也问过同样的问题,并发现答案是在使用try catch(Exception)的顶部添加以下行:

use Exception;


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接