Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[VarDumper] Ds\Map handles object keys #52495

Closed
@marc-mabe

Description

@marc-mabe

Symfony version(s) affected

6.3.x

Description

I'm using ext-ds especially Ds\Map quite often mainly because the Ds\Map allows objects as keys.
Unfortunately this breaks the VarDumper in my case triggered by the profiler:

php.CRITICAL: Uncaught Error: Symfony\Component\VarDumper\Caster\DsPairStub::__construct(): Argument #1 ($key) must be of type string|int, App\Entity\GeoCountry given, called in /app/vendor/symfony/var-dumper/Caster/DsCaster.php on line 43 {"exception":"[object] (TypeError(code: 0): Symfony\\Component\\VarDumper\\Caster\\DsPairStub::__construct(): Argument #1 ($key) must be of type string|int, App\\Entity\\\GeoCountry given, called in /app/vendor/symfony/var-dumper/Caster/DsCaster.php on line 43 at /app/vendor/symfony/var-dumper/Caster/DsPairStub.php:21)
[stacktrace]
#0 /app/vendor/symfony/var-dumper/Caster/DsCaster.php(43): Symfony\\Component\\VarDumper\\Caster\\DsPairStub->__construct(Object(App\\Entity\\\GeoCountry), Array)
#1 /app/vendor/symfony/var-dumper/Cloner/AbstractCloner.php(363): Symfony\\Component\\VarDumper\\Caster\\DsCaster::castMap(Object(Ds\\Map), Array, Object(Symfony\\Component\\VarDumper\\Cloner\\Stub), true, 0)
#2 /app/vendor/symfony/var-dumper/Cloner/VarCloner.php(130): Symfony\\Component\\VarDumper\\Cloner\\AbstractCloner->castObject(Object(Symfony\\Component\\VarDumper\\Cloner\\Stub), true)
#3 /app/vendor/symfony/var-dumper/Cloner/AbstractCloner.php(302): Symfony\\Component\\VarDumper\\Cloner\\VarCloner->doClone(Array)
#4 /app/vendor/symfony/http-kernel/DataCollector/DataCollector.php(55): Symfony\\Component\\VarDumper\\Cloner\\AbstractCloner->cloneVar(Array)
#5 /app/vendor/symfony/messenger/DataCollector/MessengerDataCollector.php(47): Symfony\\Component\\HttpKernel\\DataCollector\\DataCollector->cloneVar(Array)
#6 /app/vendor/symfony/http-kernel/Profiler/Profiler.php(100): Symfony\\Component\\Messenger\\DataCollector\\MessengerDataCollector->lateCollect()
#7 /app/vendor/symfony/http-kernel/EventListener/ProfilerListener.php(135): Symfony\\Component\\HttpKernel\\Profiler\\Profiler->saveProfile(Object(Symfony\\Component\\HttpKernel\\Profiler\\Profile))
#8 /app/vendor/symfony/event-dispatcher/Debug/WrappedListener.php(116): Symfony\\Component\\HttpKernel\\EventListener\\ProfilerListener->onKernelTerminate(Object(Symfony\\Component\\HttpKernel\\Event\\TerminateEvent), '...', Object(Symfony\\Component\\HttpKernel\\Debug\\TraceableEventDispatcher))
#9 /app/vendor/symfony/event-dispatcher/EventDispatcher.php(220): Symfony\\Component\\EventDispatcher\\Debug\\WrappedListener->__invoke(Object(Symfony\\Component\\HttpKernel\\Event\\TerminateEvent), '...', Object(Symfony\\Component\\HttpKernel\\Debug\\TraceableEventDispatcher))
#10 /app/vendor/symfony/event-dispatcher/EventDispatcher.php(56): Symfony\\Component\\EventDispatcher\\EventDispatcher->callListeners(Array, '...', Object(Symfony\\Component\\HttpKernel\\Event\\TerminateEvent))
#11 /app/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php(139): Symfony\\Component\\EventDispatcher\\EventDispatcher->dispatch(Object(Symfony\\Component\\HttpKernel\\Event\\TerminateEvent), '...')
#12 /app/vendor/symfony/http-kernel/HttpKernel.php(115): Symfony\\Component\\EventDispatcher\\Debug\\TraceableEventDispatcher->dispatch(Object(Symfony\\Component\\HttpKernel\\Event\\TerminateEvent), '...')
#13 /app/vendor/symfony/http-kernel/Kernel.php(157): Symfony\\Component\\HttpKernel\\HttpKernel->terminate(Object(Symfony\\Component\\HttpFoundation\\Request), Object(Symfony\\Component\\HttpFoundation\\Response))
#14 /app/vendor/symfony/runtime/Runner/Symfony/HttpKernelRunner.php(39): Symfony\\Component\\HttpKernel\\Kernel->terminate(Object(Symfony\\Component\\HttpFoundation\\Request), Object(Symfony\\Component\\HttpFoundation\\Response))
#15 /app/vendor/autoload_runtime.php(29): Symfony\\Component\\Runtime\\Runner\\Symfony\\HttpKernelRunner->run()
#16 /app/public/index.php(7): require_once('...')
#17 {main}

The problem happens in DsCaster::castMap:

    public static function castMap(Map $c, array $a, Stub $stub, bool $isNested): array
    {
        foreach ($c as $k => $v) {
            $a[] = new DsPairStub($k, $v);
        }

        return $a;
    }

... where DsPairStub accepts only int|string:

    public function __construct(string|int $key, mixed $value)
    {
        $this->value = [
            Caster::PREFIX_VIRTUAL.'key' => $key,
            Caster::PREFIX_VIRTUAL.'value' => $value,
        ];
    }

How to reproduce

Create a Ds\Map, put an object as key and pass it to VarDumper.

Possible Solution

Allow mixed for the $key on DsPairStub::construct - this solves the problem for me but I'm not sure what other implications this might have.

Additional Context

https://www.php.net/manual/en/ds-map.put.php

Keys of type object are supported. If an object implements Ds\Hashable, equality will be determined by the object's equals function. If an object does not implement Ds\Hashable, objects must be references to the same instance to be considered equal.

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