- vừa được xem lúc

[Laravel Architecture] Service Providers là gì?

0 0 10

Người đăng: phptojvb

Theo Viblo Asia

Như những bài của seri trước thì chúng ta đã hiểu Service Container trong Laravel là gì rồi. Tiếp tục hôm nay chúng ta sẽ đi đến tìm hiểu Service Providers, khi đã hiểu Service Container rồi thì sang phần Service Providers dễ hiểu hơn rất nhiều. Nào chúng ta cùng bắt đầu nhé! Docs của Laravel có nói

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.

Tạm dịch

Service Providers là một nơi trung tâm đặt tất cả quá trình khởi động của Laravel. Những ứng dụng của bạn cũng như những service core của Laravel sẽ được khởi động từ Service Providers.

Nghe có vẻ hơi khó hiểu nhỉ. Để mình trình bày lại một cách dễ hiểu hơn nhé. Service Provider là 1 nơi, nơi này để binding tất cả service core của Laravel cũng như service của riêng bạn vào Service Container. Chỉ đơn giản thế thôi. Như vậy Service Container là tool quản lý các class, còn Service Provider là nơi đăng ký các class vào Service Container. Thay vì viết binding các class vào Service container lung tung ở các nơi, thì ta sẽ binding các class này vào Service container ở 1 nơi nhất quán, nơi này là Service Providers. Như vậy nhìn nó chuẩn Laravel và dễ dàng quản lý hơn

Nơi khai báo config/app.php

Tất cả các Service Provider được khai báo trong config/app.php

/* |-------------------------------------------------------------------------- | Autoloaded Service Providers |-------------------------------------------------------------------------- | | The service providers listed here will be automatically loaded on the | request to your application. Feel free to add your own services to | this array to grant expanded functionality to your applications. | */ '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... */ /* * 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\RepositoryServiceProvider::class, App\Providers\ViewServiceProvider::class, /* * Custom Provider */ App\Providers\QueryBuilderTimeStampProvider::class, Aws\Laravel\AwsServiceProvider::class, ],

Mỗi Service Provider làm nhiệm vụ đăng ký 1 hay nhiều Class vào trong Service Container. Ví dụ ta cùng xem AuthServiceProvider xem nó đăng ký những Class nào nhé

<?php namespace Illuminate\Auth; use Illuminate\Auth\Access\Gate;
use Illuminate\Auth\Middleware\RequirePassword;
use Illuminate\Contracts\Auth\Access\Gate as GateContract;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Routing\ResponseFactory;
use Illuminate\Contracts\Routing\UrlGenerator;
use Illuminate\Support\ServiceProvider; class AuthServiceProvider extends ServiceProvider
{ /** * Register the service provider. * * @return void */ public function register() { $this->registerAuthenticator(); $this->registerUserResolver(); $this->registerAccessGate(); $this->registerRequirePassword(); $this->registerRequestRebindHandler(); $this->registerEventRebindHandler(); } /** * Register the authenticator services. * * @return void */ protected function registerAuthenticator() { $this->app->singleton('auth', function ($app) { // Once the authentication service has actually been requested by the developer // we will set a variable in the application indicating such. This helps us // know that we need to set any queued cookies in the after event later. $app['auth.loaded'] = true; return new AuthManager($app); }); $this->app->singleton('auth.driver', function ($app) { return $app['auth']->guard(); }); } /** * Register a resolver for the authenticated user. * * @return void */ protected function registerUserResolver() { $this->app->bind( AuthenticatableContract::class, function ($app) { return call_user_func($app['auth']->userResolver()); } ); } /** * Register the access gate service. * * @return void */ protected function registerAccessGate() { $this->app->singleton(GateContract::class, function ($app) { return new Gate($app, function () use ($app) { return call_user_func($app['auth']->userResolver()); }); }); } /** * Register a resolver for the authenticated user. * * @return void */ protected function registerRequirePassword() { $this->app->bind( RequirePassword::class, function ($app) { return new RequirePassword( $app[ResponseFactory::class], $app[UrlGenerator::class], $app['config']->get('auth.password_timeout') ); } ); } /** * Handle the re-binding of the request binding. * * @return void */ protected function registerRequestRebindHandler() { $this->app->rebinding('request', function ($app, $request) { $request->setUserResolver(function ($guard = null) use ($app) { return call_user_func($app['auth']->userResolver(), $guard); }); }); } /** * Handle the re-binding of the event dispatcher binding. * * @return void */ protected function registerEventRebindHandler() { $this->app->rebinding('events', function ($app, $dispatcher) { if (! $app->resolved('auth')) { return; } if ($app['auth']->hasResolvedGuards() === false) { return; } if (method_exists($guard = $app['auth']->guard(), 'setDispatcher')) { $guard->setDispatcher($dispatcher); } }); }
} 

Như code ta thấy AuthServiceProvider đăng ký các Class vào Service Container : AuthManager, AuthenticatableContract, RequirePassword hoặc đăng ký lại ( rebinding) các class Request, Events

Tác dụng của Service Provider

1. Là nơi khai báo tất cả các class cần thiết khi muốn khởi động ứng dụng Laravel

Như nhìn thấy ở file config/app.php ở trên thì mặc định trong list providers có 2 phần

1.1. Phần các Service Providers của Laravel Framework

 /* * 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,

1.2. Phần là các Application Service Provider

/* * 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\RepositoryServiceProvider::class, App\Providers\ViewServiceProvider::class,

2. Là nơi để khai báo các Service của bạn để bạn đăng ký vào Service Container, và sử dụng mọi nơi trong khi coding

Khi bạn muốn dùng 1 class bạn tự viết trong Laravel thì chúng ta sẽ ném class này vào Service Container cho nó quản lý, và khi dùng thì lôi ra dùng thôi. Khi ném vào Service Container thì chúng ta sẽ sử dụng Service Provider Ví dụ chúng ta có 1 class app/Providers/RepositoryServiceProvider.php B1. Viết class này trong folder app/Providers

<?php namespace App\Providers; use Illuminate\Support\ServiceProvider; class RepositoryServiceProvider extends ServiceProvider
{ /** * Register services. * * @return void */ public function register() { $this->app->bind( \App\Repositories\AdminUserRepositoryInterface::class, \App\Repositories\AdminUserRepository::class ); $this->app->bind( \App\Repositories\AdminUserForgotPasswordRepositoryInterface::class, \App\Repositories\AdminUserForgotPasswordRepository::class ); $this->app->bind( \App\Repositories\EventSettingRepositoryInterface::class, \App\Repositories\EventSettingRepository::class ); $this->app->bind( \App\Repositories\AdminUserEventSettingRepositoryInterface::class, \App\Repositories\AdminUserEventSettingRepository::class ); $this->app->bind( \App\Repositories\ContentRepositoryInterface::class, \App\Repositories\ContentRepository::class ); $this->app->bind( \App\Repositories\ContentCategoryRepositoryInterface::class, \App\Repositories\ContentCategoryRepository::class ); $this->app->bind( \App\Repositories\UserRepositoryInterface::class, \App\Repositories\UserRepository::class ); $this->app->bind( \App\Repositories\ParticipantInfoRepositoryInterface::class, \App\Repositories\ParticipantInfoRepository::class ); $this->app->bind( \App\Repositories\UserStatusRepositoryInterface::class, \App\Repositories\UserStatusRepository::class ); $this->app->bind( \App\Repositories\AdminCompanyRepositoryInterface::class, \App\Repositories\AdminCompanyRepository::class ); $this->app->bind( \App\Repositories\ViewLogRepositoryInterface::class, \App\Repositories\ViewLogRepository::class ); $this->app->bind( \App\Repositories\ContentRepositoryInterface::class, \App\Repositories\ContentRepository::class ); $this->app->bind( \App\Repositories\OptionColumnRepositoryInterface::class, \App\Repositories\OptionColumnRepository::class ); $this->app->bind( \App\Repositories\ReserveManageRepositoryInterface::class, \App\Repositories\ReserveManageRepository::class ); $this->app->bind( \App\Repositories\ContactRepositoryInterface::class, \App\Repositories\ContactRepository::class ); $this->app->bind( \App\Repositories\ContactCategoriesRepositoryInterface::class, \App\Repositories\ContactCategoriesRepository::class ); $this->app->bind( \App\Repositories\MailSendSettingRepositoryInterface::class, \App\Repositories\MailSendSettingRepository::class ); $this->app->bind( \App\Repositories\ExtractSettingRepositoryInterface::class, \App\Repositories\ExtractSettingRepository::class ); $this->app->bind( \App\Repositories\UserForgotPasswordRepositoryInterface::class, \App\Repositories\UserForgotPasswordRepository::class ); $this->app->bind( \App\Repositories\AdminUserAdminCompaniesRepositoryInterface::class, \App\Repositories\AdminUserAdminCompaniesRepository::class ); $this->app->bind( \App\Repositories\LiveSettingRepositoryInterface::class, \App\Repositories\LiveSettingRepository::class ); $this->app->bind( \App\Repositories\AdminMailSendSettingRepositoryInterface::class, \App\Repositories\AdminMailSendSettingRepository::class ); } /** * Bootstrap services. * * @return void */ public function boot() { }
} 

B2: Đăng ký Service Providers trong config/app

'providers' => [ /* * Custom Provider */ App\Providers\RepositoryServiceProvider::class, ],

B3: Lôi 1 class AdminUserRepository trong này ra dùng

app('AdminUserRepository')->getList();

3. Làm việc với các Laravel package

Khi làm việc với 1 package viết cho Laravel, điều hiển nhiên là package này phải cung cấp 1 cách thức để ae coder dùng các hàm trong package này. Theo thiết kế của các package viết cho Laravel thì nó phải cung cấp sẵn các Service Providers của riêng nó để bạn khai báo vào Service Providers của Laravel. Hãy cùng xem xét ví dụ sau: Chúng ta cần dùng các dịch vụ của AWS như s3 chẳng hạn vào dự án. Chúng ta sẽ quyết định sử dụng package của Aws, có 2 package: 1. SDK Aws cho Php của Amazon https://github.com/aws/aws-sdk-php 2. Dùng Laravel package cho Aws https://github.com/aws/aws-sdk-php-laravel Nếu dùng cách 1 thì mỗi lần dùng 1 service như S3 thì ta phải new ClientS3() ... như thế ko giống với Laravel Architecture lắm, ta nên binding ClientS3 này vào Service Container rồi lôi ra dùng. Như vậy ta sẽ dùng luôn cách thứ 2 vì package Aws viết riêng cho Laravel, cung cấp sẵn Service Providers để ta đăng ký các class của Aws vào Service Container

Dùng Laravel package cho Aws thì ta cần làm các bước sau:

1. Đăng ký Service Providers của package này vào Laravel

'providers' => array( // ... Aws\Laravel\AwsServiceProvider::class, )

2. Lôi ra dùng

$s3 = app('aws')->createClient('s3');

Bình luận

Bài viết tương tự

- vừa được xem lúc

Tìm hiểu về Resource Controller trong Laravel

Giới thiệu. Trong laravel, việc sử dụng các route post, get, group để gọi đến 1 action của Controller đã là quá quen đối với các bạn sử dụng framework này.

0 0 335

- vừa được xem lúc

Phân quyền đơn giản với package Laravel permission

Như các bạn đã biết, phân quyền trong một ứng dụng là một phần không thể thiếu trong việc phát triển phần mềm, dù đó là ứng dụng web hay là mobile. Vậy nên, hôm nay mình sẽ giới thiệu một package có thể giúp các bạn phân quyền nhanh và đơn giản trong một website được viết bằng PHP với framework là L

0 0 420

- vừa được xem lúc

Sử dụng Swagger để xây dựng API documentation

Giới thiệu về Swagger. RESTful API là một tiêu chuẩn dùng trong việc thiết kế API cho các ứng dụng web (thiết kế Web services) để tiện cho việc quản lý các resource.

0 0 1k

- vừa được xem lúc

Ví dụ CRUD với Laravel và Vuejs.

1. Cài đặt Laravel. composer create-project --prefer-dist laravel/laravel vuelaravelcrud. .

0 0 140

- vừa được xem lúc

Một số tips khi dùng laravel (Part 1)

1. Show database query in raw SQL format. DB::enableQueryLog(); // Bật tính năng query logging. DB::table('users')->get(); // Chạy truy vấn bạn muốn ghi log.

0 0 69

- vừa được xem lúc

Inertiajs - Xây dựng Single Page App không cần API

Tiêu đề là mình lấy từ trang chủ của https://inertiajs.com/ chứ không phải mình tự nghĩ ra đâu nhé :v. Lâu lâu rồi chưa động tới Laravel (dự án cuối cùng mình code là ở ver 5.8), thế nên một ngày đẹp trời lượn vào đọc docs ver 8.

0 0 227