Order of class resolution with namespaces and autoload

From: Date: Sat, 20 Oct 2007 02:42:02 +0000
Subject: Order of class resolution with namespaces and autoload
Groups: php.internals 
Request: Send a blank email to internals+get-32877@lists.php.net to get a copy of this message
Hi folks- I've hit upon something with namespaces and autoloading that I think is a little out of order. If you take the attached 3 files, put them in the same directory, and run demo.php, you will see this: Fatal error: Uncaught exception 'Exception' in /Users/chuck/Desktop/test.php:7 If you look at the code, test.php defines a Test:: namespace with a Tester class that throws an exception, test_exception.php provides an Exception derivative (Test::Exception) for that namespace, and demo.php includes test.php, sets up an __autoload function to load the exception class, and triggers the exception throwing code. However autoload is never called and the exception is of type ::Exception, because the class resolution order seems to look like this: - does the class exist (_already defined_) in the current namespace? - does the class exist in the global (non-prefixed or "::") namespace? - then try autoload What I think should happen is: - does the class exist in the current namespace? - can the class be autoloaded with the current namespace? - does the class exist in the global scope - global autoload Otherwise if you are re-defining a global class, which I imagine will be quite common with Exception at least, you will have to explicitly load your Exception classes or they'll never be used. The other alternative would be to say that if you want to use a global class inside a namespace you MUST prefix it with ::. I think this is reasonable since if you have a namespaced file it's already not going to work with anything before PHP 5.3, and that would remove the two potential autoload checks. Thanks, -chuck

<?php include './test.php'; function __autoload($class) { include './test_exception.php'; } $tester = new Test::Tester(); $tester->fail(); <?php namespace Test; class Tester { public function fail() { throw new Exception(); } } <?php namespace Test; class Exception extends ::Exception { }
« previous php.internals (#32877) next »