Stanislav Malyshev wrote: >> <?php >> namespace Foo; >> throw new Exception; >> >> In this case PHP first looks for Foo::Exception and only then for >> internal >> Exception, but the first lookup may call __autoload (or corresponding SPL >> functions) and it can emit error or throw exception. >> >> The patch provides an additional boolean argument to __autoload() that >> say >> if class is really required. In case if it false, user code shouldn't >> emit >> errors or throw exceptions. > > There's two problems here: > 1. On each access to internal class, like Exception, SPL classes, > DateTime, reflection classes, etc. - we'd have call to autoload and > subsequent disk access, maybe more than one if we have include path. > Performance of it would be awful.
This is a problem, agreed. > 2. All libraries having autoloaders would have to rewrite them to > support the new mode. This is not an issue - won't they have to support Class::Names::Like::This anyways? Backwards compatibility has already been broken. > I would propose different solution. When we have unresolved unqualified > name, we do the following: > 1. Check if we already know such class in namespace at compile-time. If > so, it's resolved. > 2. If not, will be resolved at run-time. > 3. At run-time, check if we know such class in namespace now. If yes, > it's resolved. > 4. If not, check if we know internal class with such name. If yes, it's > resolved to internal class. > 5. If not, try to autoload this class. If autoloading fails, it's the > undefined class error. The problem is that with this autoload technique this code now throws an Exception rather than a Foo::Exception: Foo/Exception.php: <?php namespace Foo; class Exception extends ::Exception {} ?> Foo/Something.php: <?php namespace Foo; function __autoload($class) { include str_replace('::', '/', $class) . '.php'; } class Something { function __construct($param) { if ($param == 3) { throw new Exception('oops'); } } } $a = new Something(3); ?> This would mean that all naming conflicts with internal classes must have a different import or be fully qualified. However, I wonder if using an import would be a clever way to get around the problem? Foo/Something.php: <?php namespace Foo; import Foo::Exception; function __autoload($class) { include str_replace('::', '/', $class) . '.php'; } class Something { function __construct($param) { if ($param == 3) { throw new Exception('oops'); } } } $a = new Something(3); ?> As I understand it, this would make the file act as if we had written it like: Foo/Something.php: <?php function __autoload($class) { include str_replace('::', '/', $class) . '.php'; } class Foo::Something { function __construct($param) { if ($param == 3) { throw new Foo::Exception('oops'); } } } $a = new Foo::Something(3); ?> If this is indeed the case, then it would satisfy my concerns with the patch and would simply be up to the documentation team to document this gotcha. Greg -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php