这更多的是为了文档,因为我已经解决了这个问题,但它很微妙,很难调试,我认为它在公共领域会很有用。
问题是,我有一个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
块中与它匹配——,我没有得到任何未解析的通知。