PHP names an anonymous class Parent@anonymous\0/path/to/file.php:LINE$N — with a NUL byte after @anonymous, the defining file and line, and a counter. The eval bridge produces a short name that contains @anonymous but no NUL, so code testing for the documented marker takes the wrong branch.
Measured
<?php
class PBase { public string $tag = "b"; }
$o = new class extends PBase {};
$n = get_class($o);
echo "has_anonymous_marker:", (str_contains($n, "@anonymous") ? "yes" : "no"), "\n";
echo "has_nul_marker:", (str_contains($n, "@anonymous\0") ? "yes" : "no"), "\n";
echo "parent:", get_parent_class($o), "\n";
echo "name_len:", strlen($n), "\n";
|
php -n 8.5.6 |
eval bridge |
contains @anonymous |
yes |
yes |
contains @anonymous\0 |
yes |
no |
get_parent_class |
PBase |
PBase |
| name length |
195 |
21 |
Why it matters
Symfony\Component\DependencyInjection\Kernel\KernelTrait builds its container class name and branches on exactly this:
$class = str_contains($class, "@anonymous\0") ? get_parent_class($class).str_replace(".", "_", ContainerBuilder::hash($class)) : $class;
With the marker missing, the raw name (which contains @) flows into a PHP-class-name regex and the kernel throws InvalidArgumentException: The environment "dev" contains invalid characters. Found exactly that way: a probe using an anonymous kernel subclass hit it, and switching the probe to a NAMED subclass made it disappear — the real --web entry point uses a named App\Kernel, so this is not currently blocking the campaign. It is filed because the name format is observable, documented, and branched on by real code.
The short name also loses the defining file and line, which is what makes php's anonymous-class names diagnosable at all.
PHP names an anonymous class
Parent@anonymous\0/path/to/file.php:LINE$N— with a NUL byte after@anonymous, the defining file and line, and a counter. The eval bridge produces a short name that contains@anonymousbut no NUL, so code testing for the documented marker takes the wrong branch.Measured
php -n8.5.6@anonymous@anonymous\0get_parent_classPBasePBaseWhy it matters
Symfony\Component\DependencyInjection\Kernel\KernelTraitbuilds its container class name and branches on exactly this:With the marker missing, the raw name (which contains
@) flows into a PHP-class-name regex and the kernel throwsInvalidArgumentException: The environment "dev" contains invalid characters. Found exactly that way: a probe using an anonymous kernel subclass hit it, and switching the probe to a NAMED subclass made it disappear — the real--webentry point uses a namedApp\Kernel, so this is not currently blocking the campaign. It is filed because the name format is observable, documented, and branched on by real code.The short name also loses the defining file and line, which is what makes php's anonymous-class names diagnosable at all.