In the previous post, we talked about the service provider, now in this section, we will use service container and will combine both to get a better understanding of this. If somehow if you don't know the service provider then you can check my previous post by clicking here. Now let's start with the service container.

For defining the service container, I want you to assume that there is a lot of books in your house and you want to sort each book on the basis of their categories and put them into boxes that are labeled. Now let's say all Philosophy books go into Philosophy box, Literature books into Literature box, Science books into Science box and Politics books in Politics box. So all books are sorted now and managed in each box. Now a person can easily pick a book because all things are clear sorted.

Similarly, the service container is the box and those boxes name are the bindings which tell that the books belong to which box. Now see the below image so that you can get better clarity on service containers.

Now, as from the above image, we can say that the box's names are binding and the box itself is the closure. Let's say you need a book which is in the science box, so you have to pick from the science box. This picking of the book from the box is known as resolving.

As in the Laravel, there are lots of methods are written but I think there are only two things first binding and the second one is resolving.

Now, you get some idea of what I am talking about. Now let see the definition, "The Laravel service container is a powerful tool for managing class dependencies and performing dependency injection.". This means mainly it is used for managing the class dependencies and dependency injections. I have shown the example of books as from the regularly used case example but now in Laravel points of view, we are managing the classes.

This comes to my first point i.e. Binding which means we need to make the box and need to labeled it with a name.

Binding

Almost all of the service container bindings will be registered within a service provider which is almost right because if you are creating the service then it will definitely load at the time of each request. But it is not compulsory you can write a service container anywhere you want unless and until you have access to the application object. See the below image this is your whole Laravel application object which I die and dumped in my application.

So, how will you get access to this application object? Hmmmmm... It is simple. Laravel provides a convenient way to access the application object and I know only three ways if you know more please mention in the comment I will update the post.

1. There is a helper method i.e. app() which returns the whole application object. This is very useful when you are not in the context of application i.e. routes, closures, controllers, etc.

2. When you are in the context of the application i.e. service provider. Then, $this->app will give you the whole application.

3. \Illuminate\Support\Facades\App::getFacadeApplication(). This is the facade which will give the same application object.

Try die and dump on all three ways i.e. dd(app(), $this->app, \Illuminate\Support\Facades\App::getFacadeApplication()). You will get the same result which I got above.

So, now you get the application object, this object has a method called bind which takes 3 arguments but for us, we need only 2. The first one name and the second one is closure.

$this->app->bind('service_container_in_app_context', function ($app) {
    // here $app is the application object
    // all your setup here
    dd('In first service container.');
});

app()->bind('service_container_from_helper', function ($app) {
    // here $app is the application object
    // all your setup here
    dd('In second service container.');
});

App::getFacadeApplication()->bind('service_container_from_facades', function ($app) {
    // here $app is the application object
    // all your setup here
    dd('In third service container.');
});

I am defining all three service containers in AppServiceProvider class because it is the place where application hits on each request. So now my class look like this,

<?php

namespace App\Providers;

use Illuminate\Support\Facades\App;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        $this->app->bind('service_container_in_app_context', function ($app) {
            // here $app is the application object
            // all your setup here
            dd('In first service container.');
        });

        app()->bind('service_container_from_helper', function ($app) {
            // here $app is the application object
            // all your setup here
            dd('In second service container.');
        });

        App::getFacadeApplication()->bind('service_container_from_facades', function ($app) {
            // here $app is the application object
            // all your setup here
            dd('In third service container.');
        });
    }

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {

    }
}

After that die and dump your application and check the binding array. You will see that all of the above service containers are registered. Below is the image, your bindings array will look like that.

Check the last three elements, you will see your container bindings. If you see your binding in the bindings array then you have successfully bound your container. Now resolve portion came into play we need to use this container.

Resolving

Now, we need to resolve containers the same I told you about the books in the very first. Now same in the application object there is a method called make which takes two parameters first one name and the second one is optional which is an array of parameters.

/* first way */
$this->app->make('service_container_in_app_context');

/* resolving same container in second way */
app()->make('service_container_in_app_context');

/* resolving same container in third way */
App::getFacadeApplication()->make('service_container_in_app_context');

/* resolving same container in fourth way */
app()['service_container_in_app_context'];

Choose these ways according to your needs let say you are in a routes file then you don't have access to the application object then, in this case, the second third and fourth case will help. If you are in a service provider then the first case is useful rather than calling helper again to get the same object.

So let's say we are in route file and we need to resolve the container. My route file will look like this,

<?php

Route::get('/', function () {
    app()->make('service_container_in_app_context');
});

After that, if you see the below image then you have successfully resolved your container.

Similarly, play with all the above methods you will get a good understanding of Laravel service container.

Conclusion

This is the first portion of the service container in which I have given the basic overview of the service container. I haven't talked about the binding by class namespace yet. Because I want you to first grab the name base knowledge. So that slowly you can get command on this. Now in the next section, I will explain all these with codebase example. I will use class namespace binding as well.

Last Modified: 5 months ago