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