kitensei
kitensei

Reputation: 2530

Laravel Dependency Injection with inheritance

Let's say I have the following case:

<?php

abstract class Service {

    protected $config;

    public function __construct($config)
    {
        $this->config = $config;
    }
}

class ClientService extends Service {

}

class ProductService extends Service {

}

Is it possible to register in my service provider the dependency injection for the Abstract parent class of my services ?

I have an API which is generated dynamically from a specification, and each one of those classes must extend the abstract Service so it can inherit for basic functionalities.

How can I Inject dependencies in my abstract service when I instantiate a child Service ?


EDIT: This question was specifically asked for Abstract class injection, without the possibility to bind the child classes which are generated automatically.

Upvotes: 9

Views: 3168

Answers (2)

James Flight
James Flight

Reputation: 1464

There are two possible things you could do here. First, if $config is a class, then you can type hint it in the abstract class:

abstract class Service {

    protected $config;

    public function __construct(ClassName $config)
    {
        $this->config = $config;
    }
}

Then every time the child classes get resolved via injection or by calling App::make('ClientService'), the config class will be injected.

If the config is not a class and can't be type hinted, you will have to bind the child classes into the container individually:

App::bind('ClientService', function () {
    // Get $config from somewhere first

    return new ClientService($config);
});

App::bind('ProductService', function () {
    // Get $config from somewhere first

    return new ProductService($config);
});

Then you will be able to call App::make('ClientService') or have it resolved via DI.

Upvotes: 4

Malitta N
Malitta N

Reputation: 3423

In your example, you have to manually pass the config object every time you instantiate from Service class or a child class.

So when you want to directly instantiate a child service, you could use something like, $cs = new ClientService(new Config());

However, you can use the real advantage of DI (since you are using Laravel), by type hinting the class name in the constructor like below.

public function __construct(\Config $config)

This way, if you do not pass a parameter when instantiating, it would by default create an object of the type-hinted class and inject it. So you could then use it like.

$cs = new ClientService();

This would inject a Laravel Config instance into the ClientService object.

Upvotes: 4

Related Questions