Extending core Laravel bindings

In this article, we are going to talk about how to extend core bindings in Laravel.

Photo by Diego PH on Unsplash

Binding and Resolution

The service container is something of a registry for a laravel application. You can store and retrieve objects in and out of the container. You define how an object should be created at one point in your application, usually, in a service provider — this is the binding — and whenever you need that object elsewhere in your application, you simply ask the service container for it and it will create that object and resolve its dependencies — the resolution.

<?phpclass Service
{
protected $dependency;
public function __construct($dependency)
{
$this->dependency = $dependency
}
public function serve()
{
//
}
}
app()->bind('service', function ($app) { 
// Make the dependency that the SC doesn't know about
$dependency = new Dependency();
return new Service($dependency);
});
$service = app()->make('service');

Extending a Service

The laravel service container provides us with ways to configure or decorate resolved services from the container. This allows us to tap into resolved services and modify them. For example, you could resolve — or simply new up an instance — a custom dependency and inject it into a core laravel binding. This ability to extend bindings gives us the flexibility we need to modify resolved services and change their behavior.

The Extend Method

Within the Container, laravel defines an extend method that lets you extend services in the container. The extend method takes the service you want to extend as the first argument and a Closure as the second. The Closure should run additional code to modify or decorate the service. It receives the original service and an instance of the container and should return the modified service:

app()->extend('service', function ($service, $app) {
return new DecoratedService($service);
});

How it works

When you call the extend method on the container and pass in the service you want to extend, laravel checks if the service already exists as a shared instance — registered as a singleton. If it does exist as a shared instance, laravel immediately calls the Closure you passed to the extend method and replaces the shared instance with the result. This then becomes the modified service.

Example — Injecting a RedisPresenceVerifier

This example demonstrates how to modify a resolved service from the container. We’ll be modifying the validator service (Illuminate\Validation\Factory) and configuring it to use a custom presence verifier that verifies against a Redis store, as opposed to the default DatabasePresenceVerifier that verifies against a database. The presence verifier is responsible for handling the unique and exists rules in a validator.

AppServiceProvider

public function testPresenceVerifierIsRedis() 
{
$this->assertInstanceOf(
RedisPresenceVerifier::class,
app('validator')->getPresenceVerifier()
);
}
// Passes

Conclusion

We’ve talked about how to extend core laravel bindings in the container but this really isn’t exclusive to core bindings, the same can be applied to any binding in the service container.

Software developer

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store