Several binding methods of Laravel service container

Binding basis

Almost all service container binding is done in the service provider.
The directory structure is as follows

Note: if a class is not based on any interface, it is not necessary to bind it to a container. The container doesn't need to be told how to build objects, because it automatically parses specific objects using PHP's reflection service.

Simple binding

In a service provider, you can access the container through the $this - > app variable, and then use the bind method to register a binding. This method requires two parameters. The first parameter is the name of the class or interface we want to register, and the second parameter is the closure of the instance of the returned class:

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

Notice that we use the container itself as a parameter to the parser, and then we can use it to resolve the child dependencies of the object we are building.

Bind a single instance

The singleton method binds a class or interface that can only be resolved once to the container, and then the next call to the container will return the same object instance:

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

Bind original value

You may have a class that receives the injection class, and you need to inject a native value such as integer. You can easily inject any value needed by this class in combination with the context:

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

Binding interface to implementation

A very powerful function of a service container is that it binds interfaces to implementations. We assume that there is an EventPusher interface and its implementation class RedisEventPusher. After writing the RedisEventPusher implementation of this interface, you can register it to the service container:

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

This code tells the container that when a class needs the implementation of EventPusher, it will inject RedisEventPusher. Now we can inject the dependency of EventPusher interface in the constructor or any other place where dependency is injected through the service container:

use App\Contracts\EventPusher;

/**
 * Create a new class instance
 *
 * @param  EventPusher  $pusher
 * @return void
 */
public function __construct(EventPusher $pusher){
    $this->pusher = $pusher;
}

Context binding

Sometimes we may have two classes that use the same interface, but we want to inject different implementations into each class. For example, two controllers depend on different implementations of the Illuminate\Contracts\Filesystem\Filesystem contract. Laravel defines a simple and smooth interface for this purpose:

use Illuminate\Support\Facades\Storage;
use App\Http\Controllers\VideoController;
use App\Http\Controllers\PhotoControllers;
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');
    });

label

In a few cases, we need to parse all bindings under a specific category. For example, you are building a Report aggregator that receives multiple different Report interface implementations. After registering the Report implementation, you can assign a tag to them through the tag method:

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

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

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

After these services are labeled, they can be easily parsed through the tagged method:

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

Extension binding

The extend method allows modifications to the resolution service. For example, when a service is parsed, additional code can be run to decorate or configure the service. The extend method receives a closure to return the modified service:

$this->app->extend(Service::class, function($service) {
    return new DecoratedService($service);
});

Tags: PHP Laravel

Posted on Thu, 11 Jun 2020 03:57:21 -0400 by ram4nd