Laravel Service Provider

Introduction

Service provider là trung tâm của tất cả các bootstrapping trong ứng dụng Laravel. Trong ứng dụng của bạn, các core serivce của Laravel, đều được bootstrap thông qua service providers.

Vậy “bootstrap” có nghĩa là gì ? “bootstrap” có nghĩa là đăng ký mọi thứ, bao gồm đăng ký các service container binding, envent listener, middleware và route… Service provider còn được biết là trung tâm cấu hình cho ứng dụng của bạn.

Nếu bạn mở file config/app.php được include trong Laravel, bạn sẽ thấy một array provider. Đây là tất cả các class service provider sẽ được load trong ứng dụng của bạn. Khi bạn tạo mới dự án, các provider được list trong mảng này là core của hệ thống. Nó sẽ bootrap một vài core như mailer, queue, cache,… và có nhiều core sẽ được deferred, có nghĩa là nó sẽ không load từ đầu, cho đến khi nào bạn dùng đến nó mới load.

Writing Service Providers

Tất cả các service provider phải extend class Illuminate\Support\ServiceProvider. Đa số các provider này sẽ chứa hai method register()boot(). Với method register(), bạn nên dùng nó trong việc bind service container

Để tạo một service provider, bạn có thể sử dụng artisan CLI với lệnh sau :

php artisan make:provider RiakServiceProvider

Một class được gen ra với cấu trúc như sau :

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class RiakServiceProvider extends ServiceProvider
{
    /**
     * Register services.
     *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * Bootstrap services.
     *
     * @return void
     */
    public function boot()
    {
        //
    }
}

1 . The Register Method

Như đã nói ở trên, bên trong method register bạn chỉ nên bind mọi thứ vào service container. Bạn đừng cố gắng đăng ký các event listeners, routes hay là các helper function trong đây. Bởi vì đôi lúc bạn sẽ không sử dụng được chúng nếu class đó chưa được tải.

Như đã nói ở bên service container, service provider luôn truy cập vào container được thông qua $app;

public function register()
{
	$this->app->singleton(Connection::class, function ($app) {
		return new Connection(config('riak'));
	});
}

The bindings And singletons Properties

Nếu service provider của bạn có nhiều binding đơn giản, bạn có thể hai property bindings and singletons hay vì bạn phải binding như cách trên với mỗi denpendency.

...

class AppServiceProvider extends ServiceProvider
{
    /**
     * All of the container bindings that should be registered.
     *
     * @var array
     */
    public $bindings = [
        ServerProvider::class => DigitalOceanServerProvider::class,
    ];

    /**
     * All of the container singletons that should be registered.
     *
     * @var array
     */
    public $singletons = [
        DowntimeNotifier::class => PingdomDowntimeNotifier::class,
        ServerProvider::class => ServerToolsProvider::class,
    ];
}

Khi service provider được load, Laravel sẽ tự động check hai properties này và tiến hành register binding chúng.

2 . The Boot Method

Method này được gọi sau khi tất cả các service providẻ đã hoàn tất việc đăng ký, nghĩa là bạn có thể truy cập vào tất cả các service được đăng ký bởi framework.

Thông thường bạn sẽ gặp nhiều nhấy là làm việc với view composer :

public function boot()
{
	View::composer('view', function () {
		//
	});
}

Boot Method Dependency Injection

Bạn cũng có thể type-hint bất denpendency vào method boot() của service provider. Service provider sẽ tự động inject bấy kì dependencies bạn cần :

use Illuminate\Contracts\Routing\ResponseFactory;

/**
 * Bootstrap any application services.
 *
 * @param  \Illuminate\Contracts\Routing\ResponseFactory  $response
 * @return void
 */
public function boot(ResponseFactory $response)
{
    $response->macro('serialized', function ($value) {
        //
    });
}

Registering Providers

Tất cả các service provider khi bạn tạo ra không tự nhiên mà nó load, nó cần phải được đăng ký trong array provider tại file config/app.php:

'providers' => [
    // Other Service Providers

    App\Providers\ComposerServiceProvider::class,
],

Deferred providers

Nếu như các service provider của bạn chỉ dành cho việc đăng ký binding, do đó bạn không muốn nó được load ngay từ đầu. Do đó, Laravel cho phép ta deferred các service provider này lại đến khi nào có yêu cầu resolve thì mới load chúng.

Để defer loading service provider, bạn chỉ cần implement nó với \Illuminate\Contracts\Support\DeferrableProvider interface và define method provides. Method provides() sẽ return về một mảng service container binding bởi provider này (để khi bạn resolve nó mới bắt đầu load service provider này):

<?php

namespace App\Providers;

use App\Services\Riak\Connection;
use Illuminate\Contracts\Support\DeferrableProvider;
use Illuminate\Support\ServiceProvider;

class RiakServiceProvider extends ServiceProvider implements DeferrableProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        $this->app->singleton(Connection::class, function ($app) {
            return new Connection($app['config']['riak']);
        });
    }

    /**
     * Get the services provided by the provider.
     *
     * @return array
     */
    public function provides()
    {
        return [Connection::class];
    }
}

Kết luận

Vậy qua trên mình cũng chia sẻ những gì mình đã tìm hiểu được về Service Provider trong Laravel. Mong rằng bài viết của mình cũng một phần nào làm sáng tỏ một chút về Service Provider. Cảm ơn các bạn đã đọc bài chia sẻ của mình.

Nguồn: https://laravel.com/docs/8.x/providers