0

Can someone help me out, everything looks normal, but dependency injection is not working for my class.

enter image description here

On register of this Service Provider, I'm telling Laravel blog is a singleton, and from reading the documentation, this should allow it to resolve when I do line 41.

But it gives me an error saying the following:

Argument 1 passed to 
Aaranmcguire\Blog\Providers\AppServiceProvider::setSettings() must 
be an instance of Aaranmcguire\Blog\Blog, none given, called in 
.../aaranmcguire/Blog/src/Providers/AppServiceProvider.php 
on line 25 and defined

If I remove line 41, then I can successfully DD the class from within the app, confirming its registered.

Any ideas as I've spent almost an hour on this?

3
  • What is calling this setSettings() method? Commented Jul 9, 2016 at 19:22
  • 1
    @El_Matella Boot() within the same ServiceProvider Commented Jul 9, 2016 at 19:38
  • @Aaran McGuire Please, don't attach code as images meta.stackoverflow.com/a/285557/5510499. Commented Jul 9, 2016 at 20:21

2 Answers 2

3

Dependency Injection only happens when using the IoC/Service container to resolve a class or call a method. If you are calling a method yourself and it has required arguments, you have to pass those arguments. Laravel does not change how PHP works.

None of these will ever involve dependency injection as they are direct method calls on an object and do not use the container:

$this->anything(); // just a method call
$something->anything(); // just another method call

The reason you will get constructor dependencies injected is because those particular classes are resolved using the IoC container. Usually the framework is the caller of such code, not you directly. When the framework calls a method on a class, it may use the container to make that call, which is where Method Injection comes into play.

The container has a call method with comment:

"Call the given Closure / class@method and inject its dependencies."

The boot method of Service Providers is called via the IoC container and that method will have dependencies injected as per the Laravel Documentation on Service Providers.

"You are able to type-hint dependencies for your service provider's boot method. The service container will automatically inject any dependencies you need..." Laravel 5.2 Docs - Service Providers - The Boot method

From Illuminate\Foundation\Application@bootProvider:

protected function bootProvider(ServiceProvider $provider)
{
    if (method_exists($provider, 'boot')) {
        return $this->call([$provider, 'boot']);
    }
}

The Application uses the call method to call the boot method on a provider, which is why you can type-hint parameters for the boot method and get Method Injection. It does not directly call boot on the provider object, it uses the container to call it.

To use features of the container, the container has to be used.

-- This is referencing Laravel 5.2, but the IoC is very much the same through the versions.

Sign up to request clarification or add additional context in comments.

Comments

2

You are mixing binding and method injection.

Binding (singleton):

public function register() {
    $this->app->singleton('blog', function () {
        return new \Blog();
    });
}

public function setSettings() {
    dd($this->app->blog);
}

Method injection:

public function setSettings(\Blog $blog) {
    dd($blog);
}

Edit: Fixing code.

2 Comments

Ok, so, why would method injection not work? its saying I'm passing in nothing, which is true because I'm expecting it to inject it. (unless it does not work inside service providers?)
The docs describe method injection as a feature of controllers. So I guess it's only available there. You can just use binding then, by removing line 41.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.