php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #76787 Namespace of anonymous class is always empty
Submitted: 2018-08-23 17:47 UTC Modified: 2018-08-25 23:01 UTC
From: marcospassos dot com at gmail dot com Assigned:
Status: Verified Package: Class/Object related
PHP Version: 7.3.0beta2 OS: MacOS 10.12.6
Private report: No CVE-ID: None
 [2018-08-23 17:47 UTC] marcospassos dot com at gmail dot com
Description:
------------
I'm not sure if it's a bug, but the namespace of an anonymous class is always empty. The behavior for closures is different although.

In our case, we would use it as the fully qualified identifier of the class, as we do with closures, but for some reason, this information is lost. Using the file path does not sound like a reasonable alternative.

Test script:
---------------
https://3v4l.org/qrcUM

Expected result:
----------------
Foo\Bar
Foo\Bar

Actual result:
--------------
Foo\Bar

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2018-08-24 00:44 UTC] carusogabriel@php.net
-Summary: Namespace of anonymous function is always empty +Summary: Namespace of anonymous class is always empty
 [2018-08-24 09:51 UTC] requinix@php.net
-Package: Reflection related +Package: Class/Object related
 [2018-08-24 09:51 UTC] requinix@php.net
Yeah, it's not technically a bug as the actual class name is more or less undefined (it's anonymous, after all) but if closures inherit namespaces then classes probably should too.

I can't imagine anyone deliberately relying on the class being a member of the global namespace so breaking this should be fine...
 [2018-08-24 12:13 UTC] cmb@php.net
-Status: Open +Status: Verified
 [2018-08-24 12:13 UTC] cmb@php.net
The basic problem is that the class name of anonymous classes
isn't prefixed with the namespace.  Adding a call to
zend_prefix_with_ns() (or doing something like this) in
zend_generate_anon_class_name()[1] would almost solve the problem.
However, that also would change the result of get_class(), for
instance, and although it is document to not rely on the class
name of anonymous classes[2], we somehow would have a BC break.

Anyhow, there is another problem, namely that the class name may
contain the file name where the anonymous class is defined, which
is not catered to by ReflectionClass::getNamespaceName() and
others, which split the class name at the last backslash.  So the
following script:

    <?php
    $reflectionClass = new \ReflectionClass(new class {});
    var_dump($reflectionClass->getShortName());

may return something like:

    string(17) "76787.php10C7504C"

[1] <https://github.com/php/php-src/blob/php-7.3.0beta2/Zend/zend_compile.c#L6283-L6295>
[2] <http://php.net/manual/en/language.oop5.anonymous.php>
[3] <https://github.com/php/php-src/blob/php-7.3.0beta2/ext/reflection/php_reflection.c#L5156-L5175>
 [2018-08-24 12:25 UTC] cmb@php.net
To clarify: the second issue affects Windows only.
 [2018-08-24 13:31 UTC] marcospassos dot com at gmail dot com
-Operating System: +Operating System: MacOS 10.12.6
 [2018-08-24 13:31 UTC] marcospassos dot com at gmail dot com
The class name on MacOS Sierra also contains the file path.
 [2018-08-24 13:51 UTC] marcospassos dot com at gmail dot com
I don't think it is a BC break, as the users are aware they should not rely on the class name for anonymous classes.

About the second issue, why not to use the same platform-independent approach adopted in closures names?

Example:

namespace Foo\Bar;

may return something like:

$reflection = new \ReflectionFunction(new function() {});
echo \get_class(new class);
echo $reflection->getName();

"Foo\Bar\{class}"
"Foo\Bar\{closure}"

In practice, we don't need the brackets as "class"  is a reserved word, so there is no way to conflict with an existing class name, but keeping it sounds more consistent.
 [2018-08-24 14:01 UTC] requinix@php.net
Is there a problem with keeping the current naming scheme and just adding in the namespace? The point is not the name of the class per se but that it should ("should") be a member of the namespace it was defined in.
 [2018-08-25 23:01 UTC] nikic@php.net
@requinix: PHP code does not have an associated namespace. A class name can be decomposed into a namespace name and a short name and that's what the reflection API does. The anonymous class name needs to have a namespace prefix if reflection is to return it.

Personally I don't think that a namespace should be returned for anon classes (or closures for that matter). At least not under the understanding that PHP namespaces are not a packaging mechanism, but compiler-aided name transformations only.

The problem mentioned by @cmb is something that we should resolve at some point though...
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Mon Dec 30 14:01:28 2024 UTC