PHP 5.3 namespace/exception gotcha
A quick heads-up for anyone who’s playing with PHP 5.3 and making use of namespaces and exceptions.
If your source file defines a namespace, all references to classes outside that namespace must be fully qualified and have a leading backslash (unless aliased by the use keyword). Unlike some other languages, PHP does not fall back to perform a search of the root namespace when a class is not found in the current namespace, and this can lead to subtle bugs in circumstances where non-existent classes may be safely referenced. While attempting to instantiate a non-existent class will always cause a fatal error, “passive” references such as those in catch clauses or instanceof expressions are permitted because the missing class could be later loaded, either explicitly or by way of an autoloader. So the following code snippet will not work as intended:
- <?php
- namespace test;
- class Foo {
- public function test() {
- try {
- something_that_might_break();
- } catch (Exception $e) {
- // won't be caught
- }
- }
- }
- ?>
In this code, the class name Exception actually resolves to test\Exception, and while this class does not exist it is still possible to refer to it without crashing your program. The exception goes uncaught, and possibly appears somewhere else further up the stack, leaving you bemused and with a precious few minutes less of your life left to make millions of money and drink beer. Instead, you must do the following:
- <?php
- namespace test;
- class Foo {
- public function test() {
- try {
- something_that_might_break();
- } catch (\Exception $e) {
- // this will work
- }
- }
- }
- ?>
I doubt this situation will improve as we get closer to 5.3 final; in order to fall back to the root namespace you would first have to exhaust the current namespace and this would necessitate the triggering any defined autoloaders and maintaining a list of namespaced classes known not to exist (which could of course change if the class was later dynamically generated via eval()). I’m not too familiar with PHP’s internals but consulting the autoloader every time a class is passively referenced would probably be prohibitively costly.

