Why does laravel IoC does not provisioning my class with my method?

632 views Asked by At

I can't get why laravel tries to create my class itself, without using my method. I can see that IoC binding is executed (POINT 1 is shown). But singleton method is being never executed. Why?

In my service provider (not deferred):

/**
 * Register the service provider.
 *
 * @return void
 */
public function register()
{
    echo "POINT 1"; // I can see this one
    $this->app->singleton(\App\Services\FooBar::class, function($app)
    {
        echo "POINT 2\n"; // Does not comes here
        return new FooBar($params);
    });
}

I try to use typehinting to resolve dependencies when creating a class:

class Test
{
    public function __construct(FooBar $fooBar)
    {

    }
}

I see that laravel tries to create FooBar to inject it, but can't resolve FooBar's dependencies. They could be resolved, if laravel would call service provider callback, but it does not. Why? How to make laravel use that callback for that class?

2

There are 2 answers

0
Maxim Lanin On BEST ANSWER

Instead of closure (that will not work), use boot() method to initiate your service.

/**
 * @param \App\Services\FooBar $foobar
 */
public function boot(\App\Services\FooBar $foobar)
{
    $foobar->setOptions(['option' => 'value']);
}

It will launch right after service will be instantiated.

4
Maksym On

It is because when you are binding a class to IoC container you are not immediately calling the closure. Instead when you need to actually do some action on your class from container you call App::make('class') which would fire the closure and give you the value that was returned from it. So for example

/**
 * Register the service provider.
 *
 * @return void
 */
public function register()
{
    echo "POINT 1"; // I can see this one
    $this->app->singleton(\App\Services\FooBar::class, function($app)
    {
        echo "POINT 2\n"; // Does not comes here
        return new FooBar($params);
    });

    $this->app->make(\App\Services\FooBar::class); //here POINT 2 will be called first.
}