Search code examples
phplaraveldesign-patternslaravel-5

What is the concept of Service Container in Laravel?


I am starting to look into Laravel but I don't understand the concept of Service Container.

How does it work and what do developers need to know to fully utilize this concept in Laravel?


Solution

  • The Service Container is the Application object: it extends the Container class, getting all of the container's functionalities.

    The advantages of using a Service Container over creating your objects manually are:

    Ability to manage class dependencies on object creation

    You define how a object should be created at one point of the application (the binding) and every time you need to create a new instance, you just ask the service container, and it will create the new instance for you, along with the required dependencies.

    For example, instead of creating objects manually with the new keyword:

    //every time we need YourClass we should pass the dependency manually
    $instance = new YourClass($dependency);
    

    you can register a binding on the Service Container:

    //add a binding for the class YourClass 
    App::bind( YourClass::class, function()
    {
        //do some preliminary work: create the needed dependencies
        $dependency = new DepClass( config('some.value') );
    
        //create and return the object with its dependencies
        return new YourClass( $dependency );
    });
    

    and create an instance through the service container with:

    //no need to create the YourClass dependencies, the Service Container will do that for us!
    $instance = App::make( YourClass::class );
    

    Binding of interfaces to concrete classes

    With Laravel automatic dependency injection, when an interface is required in some part of the app (i.e. in a controller's constructor), a concrete class is instantiated automatically by the Service Container. Changing the concrete class on the binding, will change the concrete objects instantiated through all of your app:

    //every time a UserRepositoryInterface is requested, create an EloquentUserRepository 
    App::bind( UserRepositoryInterface::class, EloquentUserRepository::class ); 
    
    //from now on, create a TestUserRepository 
    App::bind( UserRepositoryInterface::class, TestUserRepository::class );
    

    Using the Service Container as a Registry

    You can create and store unique object instances in the container and get them back later: using the App::instance method to make the binding, and thus using the container as a Registry.

    // Create an instance.
    $kevin = new User('Kevin');
    
    // Bind it to the service container.
    App::instance('the-user', $kevin);
    
    // ...somewhere and/or in another class...
    
    // Get back the instance
    $kevin = App::make('the-user');