Laravel Service Container


Laravel Service Container – The Laravel service container is a powerful tool for managing class dependencies and performing dependency injection.


Laravel Service Container.

Let us understand how to use laravel service container.

Function:-

There are some followings function available in laravel service container.

  • 1. Introduction.
  • 2. Binding.
  • 3. Resolving.
  • 4. Container Events.

1. Introduction.

It is a powerfull tool for managing class dependencies and performing dependency injection. Dependency injection is a fancy phrase that essentially means class dependencies are “injected” into the class via the constructor or, in some cases, “setter” methods.

Let’s look at a simple example.

<?php
namespace App\Http\Controllers;
use App\User;
use App\Repositories\UserRepository;
use App\Http\Controllers\Controller;

class UserController extends Controller
{
    public function __construct(UserRepository $users)
    {
        $this->users = $users;
    }

    public function show($id)
    {
        $user = $this->users->find($id);

        return view('user.profile', ['user' => $user]);
    }
}

The UserController needs to retrieve users from a data source. So, we will inject a service that is able to retrieve users. In this context our, UserRepository most likely uses Eloquent to retrieve user information from the database.

A deep understanding of the Laravel service container is essential to building a powerful, large application, as well as for contributing to the Laravel core itself.

2. Binding.

Binding Basics

Almost all of your service container bindings will be registered within Service Providers, so most of these examples will demonstrate using the container in that context.

Simple Bindings

Within a service provider, you can access to the container through the $this->app
property. We can 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->make('HttpClient'));
}
);

Note that we receive the container itself as an argument to the resolver. We can then use the container to resolve sub-dependencies of the object we are building.

Binding A Singleton

The singleton method binds a class or interface into the container that should only be resolved one time. Once a singleton binding is resolved, the same object instance will be returned on subsequent calls into the container.

$this->app->singleton('HelpSpot\API', function ($app) 
{
    return new HelpSpot\API($app->make('HttpClient'));
}
);

Binding Instances

You can also bind an existing object instance into the container using the instance method. The given instance will always be returned on subsequent calls into the container.

$api = new HelpSpot\API(new HttpClient);
$this->app->instance('HelpSpot\Api', $api);

Binding Primitives

Sometimes you may have a class that receives some injected classes but also needs an injected primitive value such as an integer. You can easily use contextual binding to inject any value your class may need

$this->app->when('App\Http\Controllers\UserController')
          ->needs('$variableName')
          ->give($value);

Binding Interfaces To Implementations

A very powerful feature of the service container is its ability to bind an interface to a given implementation. For example, suppose we have an EventPusher interface and a RedisEventPusher implementation. Once we have coded our RedisEventPusher implementation of this interface, we can register it with the service container like this:

$this->app->bind
(
    'App\Contracts\EventPusher',
    'App\Services\RedisEventPusher'
);

Now we can type-hint the EventPusher interface in a constructor, or any other location where dependencies are injected by the service container.

Let’s look at a simple example.

use App\Contracts\EventPusher;
public function __construct(EventPusher $pusher)
{
    $this->pusher = $pusher;
}

Contextual Binding

Sometimes you may have two classes that utilize the same interface, but you wish to inject different implementations into each class. For example, two controllers may depend on different implementations of the Illuminate/Contracts/Filesystem/Filesystem Contracts.

Let’s look at a simple example.

use Illuminate\Support\Facades\Storage;
use App\Http\Controllers\PhotoController;
use App\Http\Controllers\VideoController;
use Illuminate\Contracts\Filesystem\Filesystem;

$this->app->when(PhotoController::class)
          ->needs(Filesystem::class)
          ->give(function () {
              return Storage::disk('local');
          });

$this->app->when(VideoController::class)
          ->needs(Filesystem::class)
          ->give(function () {
              return Storage::disk('s3');
          });

Tagging

You may need to resolve all of a certain “category” of binding. For example, perhaps you are building a report aggregator that receives an array of many different Report interface implementations. After registering the Report implementations, you can assign them a tag using the Tag method.

Let’s look at a simple example.

$this->app->bind('SpeedReport', function () 
{
    //
});

$this->app->bind('MemoryReport', function () 
{
    //
});

$this->app->tag(['SpeedReport', 'MemoryReport'], 'reports');

Once the services have been tagged, you may easily resolve them all via the tagged method.

$this->app->bind('ReportAggregator', function ($app) 
{
    return new ReportAggregator($app->tagged('reports'));
});

3. Resolving.

The make command

You may use the make method to resolve a class instance out of the container. The make method accepts the name of the class or interface you wish to resolve.

$api = $this->app->make('HelpSpot\API');

If you are in a location of your code that does not have access to the $app variable, you may use the global resolve helper.

$api = resolve('HelpSpot\API');

Automatic Injection

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 and middleware and more.

For example, you can type-hint a repository defined by your application in a controller’s constructor. The repository will automatically be resolved and injected into the class

Let’s look at a simple example.

<?php
namespace App\Http\Controllers;

use App\Users\Repository as UserRepository;

class UserController extends Controller
{
    protected $users;
    public function __construct(UserRepository $users)
    {
        $this->users = $users;
    }
    public function show($id)
    {
        //
    }
}

4. Container Events.

The service container fires an event each time it resolves an object. You may listen to this event using the resolving methods.

Let’s look at a simple example.

$this->app->resolving(function ($object, $app) 
{
    // ...
});

$this->app->resolving(HelpSpot\API::class, function ($api, $app) 
{
    // ...
});

As we can see, the object being resolved will be passed to the callback, allowing you to set any additional properties on the object before it is given to its consumer.


Advertisements

Add Comment

đź“– Read More