Service Provider là gì? Tìm hiểu Service Provider trong Laravel

1199

Ở bài trước, đã có giải thích về việc Laravel đã xử lý một request như thế nào?. Giờ chúng ta cùng xem Service Provider hoạt động như thế nào trong ứng dụng web nhé.

Service Provider là gì?

Service Provider là thành phần trung tâm của việc khởi tạo tất cả các ứng dụng Laravel bao gồm các thành phần core. Việc đăng kí các liên kết tới service container, event listeners, middleware, và thậm chí các route. Service provider chính là nơi để cấu hình ứng dụng của bạn. Đây cũng chính là nơi khai báo các service provider sau này khi muốn viết một service provider. Hay sử dụng các package từ packagist bạn cũng thường phải khai báo thêm service provider mới tại đây.

Service Provider trong Laravel

Cùng quay lại một chút ở bài trước trong phần handle request. Đoạn này nằm xen kẽ giữa lúc Laravel nhận request và dispatch request lên router. Đây là nơi quá trình bootstrapping bắt đầu diễn ra.

Bạn có thể xem nó tại Illuminate\Foundation\Application.php Hàm này sẽ nạp các bootstrappers. Các bootstrappers ở đây được lấy từ trong hàm $this->bootstrappers(). Đó là những class sau:

Mở file Illuminate\Foundation\Application.php và tìm đến hàm bootstrapWith ta sẽ thấy hàm này sẽ tạo ra các bootstrappers mà đã liệt kê bên trên, sau đó nạp các bootstrappers này vào trong application của bạn.

Giờ chúng ta sẽ tìm hiểu xem Laravel Service provider hoạt động như thế nào nhé. Chúng ta biết biết chắc chắn là trong mỗi bootstrapper này đều có một hàm bootstrap.

Ở đây chúng ta sẽ đi vào class \Illuminate\Foundation\Bootstrap\RegisterProviders::classđể xem Service Provider đã làm những gì cho application của chúng ta:

Ở đoạn xử lý đầu tiên, $providers của chúng ta sẽ trả về một kết quả đó là danh sách các provider nằm trong key 'providers' và bắt đầu bằng Illuminate\\ tại config/app.php.

Ở đoạn xử lý thứ 2, Laravel sẽ gộp các providers có được tại hàm

vào các providers đã lấy được ở trên. Chúng ta sẽ xem các providers trong cái hàm ở trên là những providers nào nhé. Illuminate\Foundation\PackageManifest.php:

Xem hàm getManifest

Nên nhớ ở trên chúng ta make một class PackageManifest và không truyền cho nó cái gì cả. Vậy thì constructor của nó cũn không có gì. Vậy là trong hàm getManifest(), property $this->manifest ở đây đang không có giá trị.

Khởi tạo một instance từ Laravel Application

Laravel khởi tạo một instance của PackageManifest.

Trước hết hãy để ý một điều, Laravel sử dụng hàm này trước khi quá trình bootstrapping xuất hiện. Vậy lúc này trong class PackageManifest có gì ??

  Laravel 5.6 thêm Collision Package cho CLI Error Report

Chúng ta đang cần quan tâm đến hàm providers vậy nên ta cần biết tham số thứ 3 trong constructor, đó là $manifestPath là gì.
Tương ứng như chúng ta thấy, đó là:

Giờ chúng ta hiểu, giá trị $this->manifestPath chính là chuỗi bootstrap/cache/packages.php, hãy cùng tiếp tục xem Service Provider đã làm gì tiếp theo.
Mở file bootstrap/cache/packages.php , chúng ta thấy 1 array chứa các cặp array khác có key là 'providers' và 'aliases'. Mà hàm providers của chúng ta lấy các key là 'providers'
Đến đây có thể hiểu rằng Laravel sẽ lấy tất cả các providers trong application của chúng ta bằng cách lấy các providers có tiền tố Illuminate\\ tại config/app.php và danh sách các providers tại caches/packages.php. Sau khi tập hợp tất cả các providers chúng ta sẽ quay lại hàm registerConfiguredProviders():

Trong hàm này, tất cả các đăng ký các event khi load các provider, sau đó từng provider này sẽ được đăng ký bằng cách gọi đến hàm register trong class Application:

Trong hàm register tại class Application, mỗi service provider sẽ được gọi đến method register của chính provider đó.

Và nếu các bạn có để ý, trong các provider tại method register, chúng ta sẽ thường sử dụng việc binding tại hàm này, Tuy nhiên có một cách ngắn hơn đó là nếu provider của bạn đang có property là $bindings hoặc $singletons thì Laravel sẽ tự động binding theo cặp key, value này.

Đến đây, nếu application của bạn chưa nạp các provider thì nó sẽ nạp tất cả các provider đó. Nếu không, nó sẽ chỉ nạp các provider mới. Thay vì phải quay lại làm một công việc từ đầu, thì nó sẽ không làm lại nữa mà chỉ làm các công việc mới.

Giải thích ngắn gọn dễ hiểu để bạn mường tượng hơn. Ví dụ chúng ta có sẵn một bộ máy tính để bàn bao gồm CPU, chuột, bàn phím…Bạn muốn gắn thêm màn hình hay thay một bàn phím cơ khác thì chỉ cần plug and play thôi. Không phải build lại cái máy tính từ đầu.

Với Laravel cũng vậy, sau khi kết thúc quá trình bootstrapping lần đầu tiên, các package/library hiện có đã có thể sử dụng.

Giả sử bạn muốn install thêm các package/library khác thì Laravel chỉ nạp lại những package mới này và đăng ký các provider tương ứng cho chúng vào application của bạn. Vậy là chúng ta sẽ hiểu việc đăng ký providers như sau:

Vậy nên chúng ta thường thấy các provider sẽ có các phương thức như boot hay register mà không phải các phương thức khác, tất cả là do Laravel đã thiết kế nên như vậy. Đã bao giờ các bạn sử dụng command để thêm các package/library ngoài vào, sau đó thêm các provider của nó vào trong config/app.php chưa?

Thường thì chúng ta chỉ cần import nó vào và sử dụng mà không cần biết rằng tại sao nó lại vận hành được. Thật ra thì vấn đề này Laravel đã giúp chúng ta làm tất cả rồi.

Tổng kết

Service Provider là một khái niệm khá trừu tượng, và là thành phần quan trọng nhất trong quá trình handle một request trong Laravel. Hiểu một cách tổng quan là trong quá trình bootstrapping application thì Service Provider chính là phần quan trọng nhất.

  Tìm hiểu SQL Transaction và cách sử dụng trong Laravel
  Nhận diện khuôn mặt trong ứng dụng Laravel sử dụng Google Cloud Vision API
SHARE