Sayantan Das
Sayantan Das

Reputation: 1641

understand laravel dependency injection

I would like to understand how automatic dependancy injection works in laravel. I am using this library https://github.com/yedincisenol/dynamic-links . It has a service provider class which binds to the IoC container

/**
 * Register the service provider.
 *
 * @return void
 */
public function register()
{
    $this->app->singleton('DynamicLinks', function ($app) {
        return new DynamicLinks($app['config']['dynamic-links']);
    });
}

And resolving the class gives me an instance of the library class, $dynamicLinks = resolve('DynamicLinks');

As per documentaion, the class is auto injected if type hinted in the controller method,

Alternatively, and importantly, you may simply "type-hint" the dependency in the constructor of a class that is resolved by the container, including controllers, event listeners, queue jobs, middleware, and more. In practice, this is how most of your objects should be resolved by the container.

this is my controller method:

public function getLink(Request $request, DynamicLinks $dynamicLinks) {
    // other stuffs
}

But the problem is, its not getting the configuaration file in the injected instance and throwing ConfigException from the library. This is the constructor for the class

public function __construct(array $config = null)
    {
        if ($config == null) {
            $config = require_once 'config.php';
        }

        if ($config == null || !isset($config['api_key']) || strlen($config['api_key']) < 1) {
            throw new ConfigException;
        }

        $this->config   = $config;
        $this->client   =   new Client([
            'base_uri' => 'https://firebasedynamiclinks.googleapis.com/v1/shortLinks?key=' . $config['api_key']
        ]);
    }

It seems that the class is being instanciated without the config instead of using the instance registered by the provider.

Upvotes: 1

Views: 473

Answers (1)

Quezler
Quezler

Reputation: 2435

This is because the singleton is named 'DynamicLinks', which resolves to DynamicLinks

And the controller method uses the class DynamicLinks, which resolves to yedincisenol\DynamicLinks\DynamicLinks

In other words, when you expect it as argument in the controller, the service container tries to find yedincisenol\DynamicLinks\DynamicLinks, and because it is not registered as a singleton, it just tries to make to construct a new one.

-

Several solutions:

1)

Instead of having the class as controller argument, resolve it inside it as resolve('DynamicLinks')

2)

In the app/Providers/AppServiceProvider, in the register method, add:

$this->app->singleton(\yedincisenol\DynamicLinks\DynamicLinks::class, function ($app) {
    return resolve('DynamicLinks');
});

3)

fork or send a pull request to the package author to implement something along the lines of 2)

-

So in a nutshell, i recommend going for option 2), which should ensure your controller will work as intended.

Upvotes: 2

Related Questions