rafaelcpalmeida rafaelcpalmeida - 5 months ago 59
PHP Question

Unresolvable dependency resolving

I have the following code in my routes.php project.

class Foo {
public function __construct($name) {
}
}

$app->get('/', function () {
return "Ola, mundo! :)";
});

$app->group(['middleware' => 'authAPI', 'prefix' => 'api'], function () use ($app) {
$app->post('v1/payment/create', function(Foo $api){
dd($api);
});
});


When I try to access my /api/v1/payment/create this gives me the error:

Unresolvable dependency resolving [Parameter #0 [ <required> $name ]] in class Foo


Obviously I'm not passing any value to $name. My question is how to do it, the most laravelish and correct way possible.

Answer

You need to add a binding to the IOC container. https://laravel.com/docs/5.2/container#binding

In Lumen, $app is an instance of the container, so you can perform the binding in the same file as follows:

class Foo
{

    public function __construct($name)
    {

    }
}

$app->bind(Foo::class, function($app){
    return new Foo('David');
});

$app->get('/', function () {
    return "Ola, mundo! :)";
});

$app->group(['middleware' => 'authAPI', 'prefix' => 'api'], function () use ($app) {
    $app->post('v1/payment/create', function(Foo $api){
        dd($api);
    });
});

Probably you want to do this in a service provider, but as your example code has a class defined inline, i thought this the simplest way to describe the solution

Edit to address the situation whereby the $name parameter changes a lot, there are a few ways to handle it.

Ditch IOC and just create the Foo instance in the route closure:

$app->get('blah', function(){
    $foo = new Foo('blahblah');
});
$app->get('splarg', function(){
    $foo = new Foo('blobblob');
});

Alter Foo and add a setName method:

class Foo
{
    private $name;
    public function setName($name)
    {
        $this->name = $name;
    }

}

$app->get('blah', function(Foo $foo){
    $foo->setName('blahblah');
});
$app->get('splarg', function(Foo $foo){
    $foo->setName('blobblob');
});

Create a FooFactory and inject that:

Class FooFactory
{
    public function createFoo($name)
    {
        return new Foo($name);
    }
}

$app->get('blah', function(FooFactory $factory){
    $foo = $factory->createFoo('blahblah');
});
$app->get('splarg', function(FooFactory $factory){
    $foo = $factory->createFoo('blobblob');
});