Service container Laravel

ngày 31-08-2020

Service container là một khái niệm nằm trong tần Architecture Concepts (kiến trúc) của laravel, đây là một trong những phần nâng cao trong laravel và có thể được sử dụng ở nhiều nơi nhưng có thể bạn không để ý tới, hôm nay hãy cùng  daylaptrinhphp.com  nghiên cứu về định nghĩa cũng như cách sử dụng của service container trong laravel nhé 

Khuyến cáo, bài này thuộc phần nâng cao, để tránh mất tinh thần học tập cho những bạn newbie tôi khuyên các bạn chưa nên đọc bài viết này. kiến thức cần có trong bài này là laravel cơ bản, và OOP,

còn những bạn đã có kiến thức cơ bản, khi đọc bài này nên thực hành theo và nghiệm lại mới có thể hiểu được bài. các ví dụ trên ở laravel 5.8

 

1. Dependency injection là khái niệm chỉ việc lớp này được tiêm (đưa) vào một lớp khác thông qua hàm khởi tạo hoặc các phương thức setter khác

 

 

Ta có thể thấy class  UserRepository được tiêm vào hàm construct của của UserController, thay vì phải new UserRepository ở hàm show() như đoạn code có chức năng tương tự dưới đây

 

 

2. Lợi ích của việc dùng Dependency injection

 

  • Giảm sự phụ thuộc giữa các class, như các bạn thấy ở ví dụ thứ 2, class UserRepository  được new trực tiếp trong class UserController , lúc này controller của chúng ta phải phụ thuộc vào UserRepository, giả sử class UserRepository   thay đổi các tham số hoặc thuộc tính thì UserController  cũng phải thay đổi theo, sửa code trong hàm show(), đặc biệt là sẽ vất vả khi test lại

  • Code dễ bảo trì, dễ thay thế class, ở ví dụ 1 ta thấy class UserRepository được đăng kí ở contruct, nên ta có thể thay thế class khác một cách dễ dàng mà không ảnh hưởng đến code bên trong
  • Dễ dàng thấy quan hệ giữa các module (vì các dependecy đều được inject vào constructor

Vậy service container là gì: Đây là một chức năng của laravel, hỗ trợ bạn sử dụng dependecy injection dễ hàng hơn, và có thể sử dụng được ở tất cả các class chỉ cần 1 lần khai báo duy nhất, mà không cần phải thực hiện khai báo nhiều lần, 

Có lẽ đến đây các bạn vẫn còn mơ hồ nhiều nhỉ, xem ví dụ thử nhé:

Giả sử tôi có một lớp Test, và tôi muốn có thể sử dụng lớp này ở bất kì đâu trong project, tôi có thể khai báo lớp này trong AppServiceProvider để có thể sử dụng nó

 

 

Các cách đăng kí 1 service container

 

1. Binding simple

 

Ta vào App\Providers\AppServiceProvider,

ta sẽ đăng kí các service container bằng cách dùng lệnh để binding vào hàm register, ở đây tôi đăng kí MyTesting là bí danh của class Test, sau này khi muốn gọi class Test ra, ta

phải sử dung bí danh là MyTesting

 

 

Lúc này ta đã binding class Test vào service provider, để kiểm tra thử chúng ta đã đăng kí service container chưa, tôi sẽ tạo 1 controller để test thử

Trong controller mới được tạo, tôi sẽ viết đoạn mã sau để gọi class Test mà tôi đã "tiêm vào" controller đó bằng cách dùng service container

 

 

Kết quả sau khi tôi chạy controller đó là:

 

 

Các bạn đã thấy, tôi đã truy cập tới class Test mà không cần phải new Test() và có thể gọi các Thuộc tính và phương thức của nó thông qua app()->make('MyTesting').

ở đây tôi đã gọi app()->make('MyTesting') được gán vào biến $ob1, và $ob2. Như các bạn đã thấy thì kết quả của $ob1 khi tôi có

setAtt =  Lê Quốc Tịch  là "hello ban: Le Quoc Tich",

còn với $ob2, khi tôi không set setAtt chỉ là "hello ban:"

Điều đó có nghĩa là khi tôi gọi service container MyTesting lần thứ 2, (một lần gọi app()->make('MyTesting') có nghĩa là gọi servicer container 1 lần) thì class Test được khởi tạo thêm 1 lần nữa, nên phương thức setAtt =  Lê Quốc Tịch  không còn hiệu lực ở $ob2. Đó cũng là điểm khác biệt với cách đăng kí sv container thứ 2 dưới đây

 

 Cách 2: Dùng Singleton 

 

Singleton là một khái niệm nhỏ ở design pattern, cơ bản ở đây có nghĩa là chỉ cần new class (khởi tạo đối tượng) 1 lần trong object  và không cần phải khởi tạo đối tượng thêm một lần nào nữa, để hình dung hơn, tôi sẽ chia sẽ một ví dụ.

AppServicepPovider tôi lại đăng kí một service container trong register function

 

Đây là đoạn code trong TestClass

 

 

Trong file controller để test lúc nãy, tôi sẽ giữ nguyên đoạn code để gọi class Test ra

 

 

Và đây là kết quà:

 

 

Ta thấy ở lần gọi thứ 2, tôi không cần setAtt nhưng vẫn nhận được kết quả như lần trước, chứng tỏ ở lần thứ 2 này, Class test không được new lại ( new Test() ), hoặc có thể nói là đối tượng ob2 không được tạo lại, ở đây ta có $ob2 = $ob1;

 

Cách 3: Binding Instances

 

Cách này thì y chang như SingleTone, nhưng cách viết có khác chút, thay vì gọi một Closure (hàm nặc danh) thì nó sử dụng object để có thể đăng kí class một cách gọn gàng hơn, và đây là cách tôi đăng kí nó trong register() method

 

 

Kết quả thì cũng giống như Cách đăng kí singleton lúc nãy.

 

Ngoài ra còn nhiều các khác để đăng kí một SV Container, nhưng bài viết này quá dài và khó sẽ làm cho bạn đọc nản chí, Chúng tôi sẽ cập nhật trong một bài viết khác nhé, cảm ơn các bạn đã theo giõi bài viêt

Bài viết dựa theo kiến thức của người viết, có thể sẽ có sai sót đâu đó, nếu các pro nào có góp ý xin vui lòng nhắn tin qua box Face Book ở dưới nhé, xin cảm ơn