Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel 5.1 service container: Binding using something other than the class name?

Bit of a long winded question, but here goes. I'm a little confused regarding some of the documentation for the service container in Laravel 5.1. I'll explain my current understanding of the container first, and then explain where my confusion has arisen.

So, I'm fairly sure I understand the process of registering a binding with the service container. To quote the documentation, you register a binding using the bind method, passing the class or interface name that we wish to register along with a Closure that returns an instance of the class:

$this->app->bind('HelpSpot\API', function ($app) {
    return new HelpSpot\API($app['HttpClient']);
});

Now, in the Laravel 5.0 docs, that's actually stated slightly differently:

A Closure resolver is registered in the container with a key (typically the class name) and a Closure that returns some value.

So, in Laravel 5.0, it seems you were able to bind some class, say FooBar to a key that, while recommended to be the class name, could be something different, so for example:

$this->app->bind('myfoobarclass', function($app) {
    return new FooBar($app['SomethingElse']);
});

And then later you could resolve the class using:

$fooBar = $this->app->make('myfoobarclass');

However, this would remove your ability ro resolve that class using type hinting, which I'm guessing is why the docs for 5.1 states specifically to use the class name. However, in the section on Facades (http://laravel.com/docs/5.1/facades#facade-class-reference), they list the facades along with their "service container binding key", which is different to their class name. Does this mean you can't resolve these facades using type hinting? Why would they register their bindings as something other than their class name? Or is this documentation simply out of date?

If anyone could shed some light on the reasons behind this inconsistency that would be amazing, thanks in advance.

like image 517
Leon Aves Avatar asked Jan 08 '23 21:01

Leon Aves


1 Answers

You normally bind implementations to interfaces. So instead of adding something to the service container by the name of the class, you would instead use the name of an interface it implements instead:

$this->app->bind('App\HttpClientInterface', function ($app) {
    return new \Guzzle\HttpClient;
});

You can then type-hint the HttpClientInterface interface in your application, and instead get the bound GuzzleHttpClient instance. This allows you to swap your implementations out in one place without having to re-write your application code.

You’re not restricted to using fully-qualified class/interface names, you can use arbitrary strings as key names if you wish:

$this->app->bind('http.client', function () {
    return new \Guzzle\HttpClient;
});

But you can’t type-hint on these; this is where you would use the app()->make('http.client') method instead.

In regards to the Façade Class Reference section of the Laravel documentation, there are two ways of resolving the services in your app.

  1. You can type-hint on the value in the Class column, i.e. Illuminate\Contracts\Hashing\Hasher
  2. Alternatively, you can use what’s in the Service Container Binding column with the app()->make('hash') method. These are just “aliases” for the class name.

Hope this helps!

like image 132
Martin Bean Avatar answered Jan 17 '23 15:01

Martin Bean