Skip to content

Incorrect ReflectionClass::getNamespaceName for anonymous class #12895

Open

Description

@kubawerlos

Description

The following code:

<?php

namespace Foo {
    interface InterfaceFoo {}
}

namespace Bar {
    new class implements \Foo\InterfaceFoo {};
}

namespace {
    foreach (get_declared_classes() as $class) {
        if (!str_contains($class, '@anonymous')) {
            continue;
        }
        echo 'Class: ', $class, PHP_EOL;
        echo 'Namespace: ', (new ReflectionClass($class))->getNamespaceName(), PHP_EOL;
    }
}

Resulted in this output:

Class: Foo\InterfaceFoo@anonymousD:\a\php-anonymous-class-namespace\php-anonymous-class-namespace\test.php:8$0
Namespace: Foo\InterfaceFoo@anonymousD:\a\php-anonymous-class-namespace\php-anonymous-class-namespace

at Windows and

Class: Foo\InterfaceFoo@anonymous/home/runner/work/php-anonymous-class-namespace/php-anonymous-class-namespace/test.php:8$0
Namespace: Foo

at Ubuntu

But I expected this output instead:

Class: Foo\InterfaceFoo@anonymousD:\a\php-anonymous-class-namespace\php-anonymous-class-namespace\test.php:8$0
Namespace: Bar

Reproduced at https://github.com/werlos/php-anonymous-class-namespace (see the only action there).

PHP Version

8.3.0

Operating System

No response

Activity

  1. iluuu1994 commented on Dec 7, 2023

    @iluuu1994
    Member

    Hi @kubawerlos. I don't understand, why do you expect backslashes for paths on Ubuntu? The slashes are not namespace separators, its a path appended to the class name to avoid naming conflicts of anonymous classes. The class name of anonymous classes is essentially an implementation detail.

    Edit: Oh, sorry. I missed that this is talking about getNamespaceName, not the slashes.

  2. ndossche commented on Dec 7, 2023

    @ndossche
    Member

    This is because Windows paths use backslashes, but the function also uses backslashes to determine where to "cut off" the string:

    const char *backslash = zend_memrchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name));
    if (backslash) {
    RETURN_STRINGL(ZSTR_VAL(name), backslash - ZSTR_VAL(name));
    }

    Tested on my Windows 10 VM I get the same behaviour as OP.

  3. ndossche commented on Dec 7, 2023

    @ndossche
    Member

    And getShortName is also messed up as it'll return "foo.php:8$0".

  4. iluuu1994 commented on Dec 7, 2023

    @iluuu1994
    Member

    Indeed. I think OP would also expect Unix to yield Bar, but because the name is prefixed with the parent class (or first implemented interface) rather than the namespace it's also wrong.

  5. ndossche commented on Dec 7, 2023

    @ndossche
    Member

    Okay, so fixing this would consist of two parts:

    • Fix how a prefix is chosen such that the correct namespace is included in the name
    • If on Windows, and ZEND_ACC_ANON_CLASS is set, check the position of @ and search for the backslash before that

    WDYT?

  6. iluuu1994 commented on Dec 7, 2023

    @iluuu1994
    Member

    That sounds reasonable. namespace@anonymouspath:line$counter should do. I don't know what the point of including the parent class is.

  7. ndossche commented on Dec 7, 2023

    @ndossche
    Member

    I don't know what the point of including the parent class is.

    72bd559

    "This is intended to display a more useful class name in error messages
    and stack traces, and thus make debugging easier."

    I guess it doesn't really matter that much, but I did find this.

  8. ndossche commented on Dec 7, 2023

    @ndossche
    Member

    @iluuu1994 How do you want to proceed here? I have a working Windows development environment and I already know how to tackle the second bullet point.

    EDIT: or we could split the issue between us: 2nd bullet point for me and 1st for you? Just let me know so we at least don't do double work ;)

  9. iluuu1994 commented on Dec 7, 2023

    @iluuu1994
    Member

    @nielsdos However you want, I'll focus on something else tomorrow. I'm certainly not mad if you take care of either or both. ^^ I don't think this is high priority though.

  10. ndossche commented on Dec 7, 2023

    @ndossche
    Member

    Okay, will tackle this tomorrow.

  11. added a commit that references this issue on Dec 8, 2023
    75c4434
  12. Wirone commented on Mar 19, 2024

    @Wirone

    Let's code PHP like there's no tomorrow! 😀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions