How to make custom Service Providers In Laravel 7

service provicer

If you’ve ever come across the Laravel framework, it’s highly unlikely that you haven’t auricularly discerned of accommodation containers and accommodation providers. In fact, they’re the backbone of the Laravel framework and do all the heftily ponderous hoisting when you launch an instance of any Laravel application.

In this article, we’re going to have a glimpse of what the accommodation container is all about, and following that we’ll discuss the accommodation provider in detail. In the course of this article, I’ll withal demonstrate how to engender a custom accommodation provider in Laravel. Once you engender an accommodation provider, you additionally need to register it with the Laravel application in order to genuinely utilize it, so we’ll go through that as well.

There are two consequential methods, boot and register, that your accommodation provider may implement, and in the last segment of this article we’ll discuss these two methods exhaustively.

Before we dive into the discussion of a service provider, I’ll try to introduce the service container as it will be used heavily in your service provider implementation.

Understand Service Containers and Service Providers

What Is a Service Container?

In the simplest terms, we could verbally express that the accommodation container in Laravel is a box that holds sundry components’ bindings, and they are accommodated as needed throughout the application.

In the words of the official Laravel documentation:

The Laravel accommodation container is a puissant implement for managing class dependencies and performing dependency injection.

So, whenever you require to inject any built-in component or accommodation, you could indite hint it in your constructor or method, and it’ll be injected automatically from the accommodation container as it contains everything you require! Isn’t that cool? It preserves you from manually instantiating the components and thus evades tight coupling in your code.

Let’s have a look at a quick example to understand it.

Class SomeClass
{
    public function __construct(FooBar $foobarObject)
    {
        // use $foobarObject object
    }
}

As you can visually perceive, the SomeClass needs an instance of FooBar to instantiate itself. So, fundamentally, it has a dependency that requires to be injected. Laravel does this automatically by looking into the accommodation container and injecting the felicitous dependency.

And if you’re wondering how Laravel kens which components or accommodations to include in the accommodation container, the answer is the accommodation provider. It’s the accommodation provider that tells Laravel to bind sundry components into the accommodation container. In fact, it’s called accommodation container bindings, and you require to do it via the accommodation provider.

So it’s the accommodation provider that registers all the accommodation container bindings, and it’s done via the register method of the accommodation provider implementation.

That should bring another question on the table: how does Laravel ken about sundry accommodation providers? Did you just verbally express anything? I’ve just auricularly discerned someone verbalizing that, Laravel should decipher that automatically additionally! Oh boy, that’s an inordinate amount of to ask: Laravel is a framework not a superman, isn’t it? Kidding apart, that’s something you require to apprise Laravel explicitly.

Go ahead and visually examine the contents of the config/app.php file. You’ll find an array ingress that lists all the accommodation providers that will be loaded during the bootstrapping of the Laravel application.

'providers' => [
  
        /*
         * Laravel Framework Service Providers...
         */
        Illuminate\Auth\AuthServiceProvider::class,
        Illuminate\Broadcasting\BroadcastServiceProvider::class,
        Illuminate\Bus\BusServiceProvider::class,
        Illuminate\Cache\CacheServiceProvider::class,
        Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class,
        Illuminate\Cookie\CookieServiceProvider::class,
        Illuminate\Database\DatabaseServiceProvider::class,
        Illuminate\Encryption\EncryptionServiceProvider::class,
        Illuminate\Filesystem\FilesystemServiceProvider::class,
        Illuminate\Foundation\Providers\FoundationServiceProvider::class,
        Illuminate\Hashing\HashServiceProvider::class,
        Illuminate\Mail\MailServiceProvider::class,
        Illuminate\Notifications\NotificationServiceProvider::class,
        Illuminate\Pagination\PaginationServiceProvider::class,
        Illuminate\Pipeline\PipelineServiceProvider::class,
        Illuminate\Queue\QueueServiceProvider::class,
        Illuminate\Redis\RedisServiceProvider::class,
        Illuminate\Auth\Passwords\PasswordResetServiceProvider::class,
        Illuminate\Session\SessionServiceProvider::class,
        Illuminate\Translation\TranslationServiceProvider::class,
        Illuminate\Validation\ValidationServiceProvider::class,
        Illuminate\View\ViewServiceProvider::class,
  
        /*
         * Package Service Providers...
         */
        Laravel\Tinker\TinkerServiceProvider::class,
  
        /*
         * Application Service Providers...
         */
        App\Providers\AppServiceProvider::class,
        App\Providers\AuthServiceProvider::class,
        // App\Providers\BroadcastServiceProvider::class,
        App\Providers\EventServiceProvider::class,
        App\Providers\RouteServiceProvider::class,
],

So, that was the accommodation container at your disposal. From the next section onwards, we’ll fixate on the accommodation provider, which is the main topic of this article!

What Is a Service Provider?

If the accommodation container is something that sanctions you to define bindings and inject dependencies, then the accommodation provider is the place where it transpires.

Let’s have an expeditious visually examine one of the core accommodation providers to understand what it does. Go ahead and open the vender/laravel/framework/src/Illuminate/Cache/CacheServiceProvider.php file.

The paramount thing to note here is the register method, which sanctions you to define accommodation container bindings. As you can optically discern, there are three bindings for the cache, cache.store and memcached.connector accommodations.

Fundamentally, we’re apprising Laravel that whenever there’s a desideratum to resolve a cache ingression, it should return the instance of CacheManager. So we’re just integrating a kind of mapping in the accommodation container that can be accessed via $this->app.

This is the congruous way to integrate any accommodation to a Laravel accommodation container. That additionally sanctions you to realize the more immensely colossal picture of how Laravel goes through the register method of all accommodation providers and populates the accommodation container! And as we’ve mentioned earlier, it picks up the list of accommodation providers from the config/app.php file.

And that’s the story of the accommodation provider. In the next section, we’ll discuss how to engender a custom accommodation provider so that you can register your custom accommodations into the Laravel accommodation container.

Create Your Custom Service Provider

Laravel already comes with a hands-on command-line utility implement, artisan, which sanctions you to engender template code so that you don’t have to engender it from scratch. Go ahead and pergrinate to the command line and run the following command in your application root to engender a custom accommodation provider.

$php artisan make:provider EnvatoCustomServiceProvider
Provider created successfully.

And that should engender the file EnvatoCustomServiceProvider.php under the app/Providers directory. Open the file to optically discern what it holds.

<?php
namespace App\Providers;
  
use Illuminate\Support\ServiceProvider;
  
class EnvatoCustomServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot()
    {
        //
    }
  
    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

As we discussed earlier, there are two methods, boot and register, that you’ll be dealing with most of the time when you work with your custom accommodation provider.

The register method is the place where you define all your custom accommodation container bindings. On the other hand, the boot method is the place where you can consume already registered accommodations via the register method. In the last segment of this article, we’ll discuss these two methods in detail as we’ll go through some practical use cases to understand the utilization of both the methods.

Register Your Custom Service Provider

So you’ve engendered your custom accommodation provider. That’s great! Next, you require to apprise Laravel about your custom accommodation provider so that it can load it along with other accommodation providers during bootstrapping.

To register your accommodation provider, you just need to integrate an ingression to the array of accommodation providers in the config/app.php file.

'providers' => [
  
        /*
         * Laravel Framework Service Providers...
         */
        Illuminate\Auth\AuthServiceProvider::class,
        Illuminate\Broadcasting\BroadcastServiceProvider::class,
        Illuminate\Bus\BusServiceProvider::class,
        Illuminate\Cache\CacheServiceProvider::class,
        Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class,
        Illuminate\Cookie\CookieServiceProvider::class,
        Illuminate\Database\DatabaseServiceProvider::class,
        Illuminate\Encryption\EncryptionServiceProvider::class,
        Illuminate\Filesystem\FilesystemServiceProvider::class,
        Illuminate\Foundation\Providers\FoundationServiceProvider::class,
        Illuminate\Hashing\HashServiceProvider::class,
        Illuminate\Mail\MailServiceProvider::class,
        Illuminate\Notifications\NotificationServiceProvider::class,
        Illuminate\Pagination\PaginationServiceProvider::class,
        Illuminate\Pipeline\PipelineServiceProvider::class,
        Illuminate\Queue\QueueServiceProvider::class,
        Illuminate\Redis\RedisServiceProvider::class,
        Illuminate\Auth\Passwords\PasswordResetServiceProvider::class,
        Illuminate\Session\SessionServiceProvider::class,
        Illuminate\Translation\TranslationServiceProvider::class,
        Illuminate\Validation\ValidationServiceProvider::class,
        Illuminate\View\ViewServiceProvider::class,
  
        /*
         * Package Service Providers...
         */
        Laravel\Tinker\TinkerServiceProvider::class,
  
        /*
         * Application Service Providers...
         */
        App\Providers\AppServiceProvider::class,
        App\Providers\AuthServiceProvider::class,
        // App\Providers\BroadcastServiceProvider::class,
        App\Providers\EventServiceProvider::class,
        App\Providers\RouteServiceProvider::class,
        App\Providers\EnvatoCustomServiceProvider::class,
],

And that’s it! You’ve registered your accommodation provider with Laravel’s scheme of things! But the accommodation provider we’ve engendered is virtually a blank template and of no avail at the moment. In the next section, we’ll go through a couple of practical examples to visually perceive what you could do with the register and boot methods.

Go Through the Register and Boot Methods

To commence with, we’ll go through the register method to understand how you could genuinely utilize it. Open the accommodation provider file app/Providers/EnvatoCustomServiceProvider.php that was engendered earlier and supersede the subsisting code with the following.

<?php
namespace App\Providers;
  
use Illuminate\Support\ServiceProvider;
use App\Library\Services\DemoOne;
  
class EnvatoCustomServiceProvider extends ServiceProvider
{
    public function boot()
    {
    }
  
    public function register()
    {
        $this->app->bind('App\Library\Services\DemoOne', function ($app) {
          return new DemoOne();
        });
    }
}

There are two important things to note here:

We’ve imported App\Library\Accommodations\DemoOne so that we can utilize it. The DemoOne class isn’t engendered yet, but we’ll do that in a moment.
In the register method, we’ve utilized the bind method of the accommodation container to integrate our accommodation container binding. So, whenever the App\Library\Accommodations\DemoOne dependency needs to be resolved, it’ll call the closure function, and it instantiates and returns the App\Library\Accommodations\DemoOne object.


So you just need to engender the app/Library/Accommodations/DemoOne.php file for this to work.

<?php
namespace App\Library\Services;
  
class DemoOne
{
    public function doSomethingUseful()
    {
      return 'Output from DemoOne';
    }
}

And here’s the code somewhere in your controller where the dependency will be injected.

<?php
namespace App\Http\Controllers;
  
use App\Http\Controllers\Controller;
use App\Library\Services\DemoOne;
  
class TestController extends Controller
{
    public function index(DemoOne $customServiceInstance)
    {
        echo $customServiceInstance->doSomethingUseful();
    }
}

That’s a very simple example of binding a class. In fact, in the above example, there’s no desideratum to engender an accommodation provider and implement the register method as we did, since Laravel can automatically resolve it utilizing reflection.

A very important note from the Laravel documentation:

There is no desideratum to bind classes into the container if they do not depend on any interfaces. The container does not require to be authoritatively mandated on how to build these objects, since it can automatically resolve these objects utilizing reflection.

On the other hand, it would have been authentically subsidiary if you had bound an interface to a certain implementation. Let’s go through an example to understand it.

Let’s create a very simple interface at app/Library/Services/Contracts/CustomServiceInterface.php.

<?php
// app/Library/Services/Contracts/CustomServiceInterface.php
namespace App\Library\Services\Contracts;
  
Interface CustomServiceInterface
{
    public function doSomethingUseful();
}

Next, let’s engender two concrete implementations of this interface. Fundamentally, we just need to engender two classes that elongate the CustomServiceInterface interface.

Create the DemoOne class in app/Library/Services/DemoOne.php.

<?php
// app/Library/Services/DemoOne.php
namespace App\Library\Services;
  
use App\Library\Services\Contracts\CustomServiceInterface;
  
class DemoOne implements CustomServiceInterface
{
    public function doSomethingUseful()
    {
      return 'Output from DemoOne';
    }
}

Similarly, DemoTwo goes in app/Library/Services/DemoTwo.php.

<?php
// app/Library/Services/DemoTwo.php
namespace App\Library\Services;
  
use App\Library\Services\Contracts\CustomServiceInterface;
  
class DemoTwo implements CustomServiceInterface
{
    public function doSomethingUseful()
    {
      return 'Output from DemoTwo';
    }
}

Now, in lieu of binding a class, we’ll bind an interface. Revisit EnvatoCustomServiceProvider.php and transmute the code as shown below.

<?php
namespace App\Providers;
  
use Illuminate\Support\ServiceProvider;
use App\Library\Services\DemoOne;
  
class EnvatoCustomServiceProvider extends ServiceProvider
{
    public function boot()
    {
    }
  
    public function register()
    {
        $this->app->bind('App\Library\Services\Contracts\CustomServiceInterface', function ($app) {
          return new DemoOne();
        });
    }
}

In this case, we’ve bound the App\Library\Accommodations\Contracts\CustomServiceInterface interface to the DemoOne implementation. Hence, whenever the App\Library\Accommodations\Contracts\CustomServiceInterface dependency needs to be resolved, it instantiates and returns the App\Library\Accommodations\DemoOne object. Now it makes more sense, doesn’t it?

Let’s quickly revise the controller code as well.

<?php
namespace App\Http\Controllers;
  
use App\Http\Controllers\Controller;
use App\Library\Services\Contracts\CustomServiceInterface;
  
class TestController extends Controller
{
    public function index(CustomServiceInterface $customServiceInstance)
    {
        echo $customServiceInstance->doSomethingUseful();
    }
}

As you may have conjectured, the $customServiceInstance should be the instance of App\Library\Accommodations\DemoOne! The resplendency of this approach is that you can swap the DemoOne implementation with the other one facilely.

Let’s verbally express you optate to utilize the DemoTwo implementation in lieu of DemoOne. In that case, you just need to make the following vicissitudes in the accommodation provider EnvatoCustomServiceProvider.php.

Find the following line:

use App\Library\Services\DemoOne;

And replace it with:

use App\Library\Services\DemoTwo;

Similarly, find this one:

return new DemoOne();

That should be replaced by:

return new DemoTwo();

The same approach can be used should you optate to supersede any core implementation with your own. And it’s not only the bind method you could utilize for your accommodation container bindings; the Laravel accommodation container provides sundry ways of binding into the accommodation container. Please check the official Laravel documentation for the consummate reference.

The next candidate is the boot method, which you could utilize to elongate the core Laravel functionality. In this method, you could access all the accommodations that were registered utilizing the register method of the accommodation provider. In most cases, you optate to register your event listeners in this method, which will be triggered when something transpires.

Let’s have a look at a couple of examples that require the boot method implementation.

You want to add your own custom form field validator to Laravel.

public function boot()
{
    Validator::extend('my_custom_validator', function ($attribute, $value, $parameters, $validator) {
        // validation logic goes here...
    });
}

Should you optate to register a view composer, it’s the impeccable place to do that! In fact, we could verbally express that the boot method is frequently used to integrate view composers!

public function boot()
{
    View::composer(
        'demo', 'App\Http\ViewComposers\DemoComposer'
    );
}

Of course, you optate to import a facade Illuminate\Support\Facades\View in your accommodation provider in the first place.

In the same territory, you could share the data across multiple views as well!

public function boot()
{
    View::share('key', 'value');
}

It can also be used to define explicit model bindings.

public function boot()
{
    parent::boot();
  
    Route::model('user', App\User::class);
}

These were a few examples to demonstrate the utilization of the boot method. The more you get into Laravel, the more reasons you’ll find to implement it!

And with that, we’ve reached the cessation of this article. I hope you’ve relished the topics that were discussed throughout this article.

Conclusion

It was the discussion of accommodation providers that was the center magnetization of this article, albeit we commenced our article with the accommodation container as that was a consequential ingredient in order to understand the accommodation provider.

Following that, we developed a custom accommodation provider, and in the latter a moiety of the article we went through a couple of practical examples.

For those of you who are either just getting commenced with Laravel or looking to expand your cognizance, site, or application with extensions, we have a variety of things you can study at Envato Market.

If you’ve any queries or comments, just shoot it using the feed below!

About OakML

Hi we are enthusiastic developers team, we try to serve some good idea to open source community

Leave a Reply

Your email address will not be published. Required fields are marked *

Subscribe To Our Newsletter
Enter your email to receive a weekly round-up of our best posts. Learn more!