Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 922
kitensei Avatar asked Jun 18 '15 06:06

kitensei


2 Answers

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.

like image 89
Malitta N Avatar answered Sep 21 '22 01:09

Malitta N


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.

like image 3
James Flight Avatar answered Sep 21 '22 01:09

James Flight