laravel / ideas

Issues board used for Laravel internals discussions.
939 stars 28 forks source link

Laravel's container is unable to resolve ellipsis symbol (failing with an Unresolvable primitive) #1882

Open 6562680 opened 5 years ago

6562680 commented 5 years ago

Description:

Laravel fails where we try to bind class where we have ...$arguments in constructor Got the error when trying to make library with clever argument resolving (put via string, arrays or dicts)

Steps To Reproduce:

interface DependInterface {}
interface MyObjectInterface {}

Class Depend implements DependInterface {}
Class MyObject implements MyObjectInterface { public function __construct(DependInterface $depend, ...$arguments) {} }

// provide

$app->bind(DependInterface::class, Depend::class);
$app->bind(MyObjectInterface::class, MyObject::class);

$app->make(MyObjectInterface::class); // Unresolvable primitive exception

I think in Container forgotten block with checking $reflectionArgument->allowsNull() exactly for ellipsis-like arguments.

driesvints commented 5 years ago

Hey @6562680. This is expected. Because ...$arguments isn't a class based argument the container can't resolve it. Variadic parameters can't have a default either so this construct denotes that at least one argument is needed.

What you might be looking for is binding primitives: https://laravel.com/docs/6.x/container#binding-basics

        $this->app->when(MyObject::class)
            ->needs('$arguments')
            ->give(function () {
                return [];
            });
6562680 commented 5 years ago

Of course if you set type you shoul pass the value, but even then you can pass null or skip arguments to get empty array there. If you want argument you should declare (arg, ...args) there. Reflection class returns allowNull true, because its possible, man! Variadic parameter is nullable by default

driesvints commented 5 years ago

@6562680 in any case this is more of a discussion for the ideas repo so I've moved it here.