在对象方法中未捕获异常


Exception not being caught inside object method

这更多的是为了文档,因为我已经解决了这个问题,但它很微妙,很难调试,我认为它在公共领域会很有用。

问题是,我有一个try/catch块在对象方法,只是不工作。简化后的示例位于两个文件中,如下所示:

TestClass.php:

<?php
//TestClass.php
namespace MyTest;
class TestClass {
    public function __construct() {
        'e("Initializing object");
        try {
            'e("Trying object exception");
            'throwTestException("Failing gracefully in object");
            'e("After exception");
        } catch (Exception $e) {
            'e($e->getMessage());
        }
        'e("After object init exception");
    }
}
?>

Main.php:

<?php
//Main.php
function e($str) { echo "'n$str"; }
function throwTestException($msg) {
    throw new RuntimeException($msg);
}
require "TestClass.php";
e("Beginning");
try {
    e("First try");
    throwTestException("Failing gracefully first");
    e("After exception");
} catch (Exception $e) {
    e($e->getMessage());
}
e("Ending");
e('');
e('Beginning object test');
new 'MyTest'TestClass();
e('Ending object test');
?>

加载Main.php的预期结果是:

Beginning
First try
Failing gracefully first
Ending
Beginning object test
Initializing object
Trying object exception
Failing gracefully in object
After object init exception
Ending object test

我实际得到的是这样的:

Beginning
First try
Failing gracefully first
Ending
Beginning object test
Initializing object
Trying object exception
Fatal Error: Uncaught Exception: Failing gracefully in object......

可以看到,异常没有被捕获。我试了各种各样的方法,就是不明白为什么它没有被抓住。然后……

我意识到这是一个名称空间问题。因为我在名称空间MyTest中声明了TestClass,在全局名称空间中声明了throwTestException,所以我在类方法中对Exception的引用默认地解析为'MyTest'Exception,因此与实际抛出的异常'RuntimeException不匹配。由于我实际上并没有试图从名称空间中实例化异常,因此没有出现"未知类"错误来揭示发生了什么。

那么,解决方案就是正确地解析我试图捕获的异常类:
catch('Exception $e) { .... }

公平地说,当我构建高度简化的示例时,这一点变得很明显。它最初并不明显,因为我期望捕获的异常是由类的超类(即SQLite3类)生成的。因此,在生成异常时,我不必担心名称空间,在捕获异常时,我所考虑的就是使用最通用的异常形式Exception。再一次,因为我没有实例化那个异常——只是在catch块中与它匹配——,我没有得到任何未解析的通知。