Laravel Service Providers
Tags: laravel, architecture
Published: 2020-07-17 13:07:49

In this post, we will discuss **Service Providers** and how Service Providers used to register classes. There are two important methods of service providers <code>Boot</code> and <code>Register</code>. So will discuss these two methods. 

> Service providers are the central place of all Laravel application bootstrapping. Your own application, as well as all of Laravel's core services, are bootstrapped via service providers.

In simple terms, Service Provider is used for registering things, including registering service container bindings. So it's a place where you can register service container bindings.

Service providers contains <code>register</code> and <code>boot</code> method. Within the <code>register</code> method, you should only define service container bindings. You have always access to service containers from service provider via <code>$this->app</code>.

To register the service provider, you just need to add an entry to the provider's array in the <code>config/app.php</code> file. These are all of the service provider classes that will be loaded for your application.

Let's understand both methods <code>register</code> and <code>boot</code> by creating a custom service provider. 

In Laravel, you can use the command-line utility tool *Artisan* to create custom providers. Just hit below artisan command to create a provider.
```
php artisan make:provider ProductServiceProvider
```

This will create new file <code>ProductServiceProvider.php</code> under *app/providers*. 

The content of this file will be looks like :
```php
<?php

namespace App\Providers;
  
use Illuminate\Support\ServiceProvider;
  
class ProductServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot()
    {
        //
    }
  
    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}
```
Here, we have created our first custom service provider Now add an entry in providers array under <code>config/app.php</code> file so that laravel loads this provider along with other providers during bootstrapping process. 

So open <code>config/app.php</code> file and append line <code>App\Providers\ProductServiceProvider::class</code>
```php
'providers' => [
        App\Providers\ProductServiceProvider::class,
],
```
Till now we have created a custom service provider and added an entry on providers array. But still, our service provider doesn't do anything special here. it's just a blank template. So let's try to register class binding inside the <code>register</code> method. 

Open <code>ProductServiceProvider.php</code> file and update with below code :
```php
<?php

namespace App\Providers;
  
use Illuminate\Support\ServiceProvider;
use App\Library\ProductClass;
use App\Repositories\ProductRepository;
  
class ProductServiceProvider extends ServiceProvider
{
    public function boot()
    {
    }
  
    public function register()
    {
        $this->app->bind(ProductRepository::class, ProductClass::class);
    }
}
```
In the <code>register</code> method, we've added our service container binding. So, whenever the <code>App\Repositories\ProductRepository</code> dependency needs to be resolved, it'll call the closure function, and it returns the instance of <code>App\Library\ProductClass class</code>.

Let's create <code>ProductRepository</code> and <code>ProductClass</code> :

<code>App\Repositories\ProductRepository.php</code>
```php
<?php

namespace App\Repositories;
  
Interface ProductRepository
{
    public function listAll();
}
```
<code>App\Library\ProductClass.php</code> 
```php
<?php

namespace App\Library;

use App\Repositories\ProductRepository;
use App\Models\Products;

class ProductClass implements ProductRepository
{
    public function listAll()
    {
        return Products::all();
    }
}
```
So we have <code>ProductClass</code> and <code>ProductRepository</code> class created. Now inject dependency somewhere on a controller. 

For that, create Controller and put below code inside it :
```php
<?php

namespace App\Http\Controllers;
  
use App\Http\Controllers\Controller;
use App\Repositories\ProductRepository;
  
class ProductController extends Controller
{
    protected $prodRepository;

    public function __construct(ProductRepository $prodRepository)
    {
        $this->prodRepository = $prodRepository;
    }

    public function index()
    {
        $products = $this->prodRepository->listAll();
        return view('prodducts.list',['products'=>$products]);
    }
}
```
When the above code executed it will list products on the webpage. This is a basic concept of the service provider and the beauty of this concept is you can easily swap to other implementation. If you need implementation of <code>SomeOtherClass</code> instead of <code>ProductClass</code> then you just need to update <code>ProductServiceProvider</code> binding with other classes.

That's it, We have created custom service provider <code>ProductServiceProvider</code> and bind the <code>ProductRepository</code> interface inside the <code>register</code> method. Then we create <code>ProductClass</code> which implements the <code>ProductRepository</code> interface. And demonstrate how dependency injected on <code>ProductController</code>.

###Boot Method 

Boot method, which you can use to extend the core functionality or create custom functionality. In this method, you could access all the services that were registered using the <code>register</code> method of the service provider.

**For Example,**

*You could use this method to add a custom validator,*
```php
public function boot()
{
    Validator::extend('custom_validator', function ($attribute, $value, $parameters, $validator) {
        // validation logic goes here...
    });
}
```
*You could use to register a view composer,*
```php
public function boot()
{
    View::composer(
        'custom', 'App\Http\ViewComposers\CustomComposer'
    );
}
```
*You could use to share the data across multiple views,*
```php
public function boot()
{
    View::share('key', 'value');
}
```
Hope this post helps you to understand Service Provider uses and the creation of custom service providers.

Thank you.