Tự build 1 Dependency Injection Container với PHP

Tram Ho

Nếu bạn đã làm việc với các Framework như Laravel thì chắc hẳn bạn sẽ biết đến Service Container. Service Container trong Laravel là một Dependency Injection (DI) Container, là nơi quản lý class dependency và thực hiện dependency injection.

Để sử dụng Service Container thì khá đơn giản tuy nhiên tìm hiểu cách nó được xây dựng như thế nào thì là một vấn đề khác. Trong bài viết này mình sẽ giới thiệu một vài kiến thức mà Laravel áp dụng để xây dựng Service Container, từ đó thử build 1 mini Dependency Injection (DI) Container tương tự Service Container xem sao nhé.

Nội dung bài viết:

  • Dependency Injection
  • Reflection (QUAN TRỌNG)
  • Build mini DI Container

Trong đấy quan trọng nhất là Reflection, đây là vấn đề mấu chốt để xây dựng DI container.

Dependency Injection

Nếu một Class A hoạt động phụ thuộc vào một vài Class khác, thay vì khởi tạo các instance của các Class kia bên trong Class A, ta sẽ inject những instance đó vào thông qua constructor hay setter. Những instance của các Class mà Class A cần để hoạt động đó được gọi là dependency.

Ví dụ:

Có thể thấy để UserController hoạt động cần 1 instance UserService, tương tự để UserService hoạt động cần 1 instance UserRepositoryInterface.

Ở đây chúng ta đã áp dụng DI bằng cách inject các class dependency thông qua constructor như ví dụ trên.

Tuy nhiên khi sử dụng UserController

Sẽ ra sao nếu như class có nhiều dependency, và những dependency này lại có nhiều dependency khác?

Ví dụ như UserService cần GroupService, GroupService cần GroupRepository:

Đây chính là lúc bạn cần DI Container để giải quyết vấn đề trên. Sức mạnh của DI Container là ở chỗ, bạn có thể “type-hint” dependency trong constructor hoặc method của class, nó sẽ tự động resolve và inject nó vào class cho bạn. Sử dụng Reflection là cách DI Container làm nên điều kì diệu đấy.

Reflection

Nguyên văn từ PHP:

PHP 5 comes with a complete reflection API that adds the ability to reverse-engineer classes, interfaces, functions, methods and extensions. Additionally, the reflection API offers ways to retrieve doc comments for functions, classes and methods.

Dịch nôm na: Reflection là khả năng để chương trình “inspect” chính nó, bạn có thể khảo sát class, interface, function, method và cả extension xem nó tên gì, cần gì,… Nó còn có thể lấy được comment của function, class, method.

Mình sẽ giới thiệu với bạn 1 vài build-in function của Reflection sẽ áp dụng vào việc xây dựng DI Container dưới đây, chi tiết hơn bạn có thể vào docs Reflection.

Laravel Service Container là một DI Container, về cơ bản thì Laravel sử dụng Reflection kết hợp đệ quy để resolve các dependency từ đấy tạo nên sức mạnh của Service Container mà bạn đã thấy.

Chưa tin thì bạn vào đây https://github.com/laravel/framework/blob/master/src/Illuminate/Container/Container.php

Tại function build (dòng 793)

Chưa biết thế nào nhưng có từ ReflectionClass thì chắc là đúng rồi?

Build Mini DI Container

Ok giờ đến cách xây dựng DI như thế nào, mời bạn xem source code dưới đây, chi tiết mình đã comment từng function. Có gì không hiểu bạn cứ comment phía dưới nhé.

Mini DI Container

Chúng ta sẽ thử sử dụng class Container vừa mới xây dựng áp dụng vào ví dụ đầu bài nhé.

Hoặc bạn cũng có thể bind 1 Closure (kèm params)

Trên đây mình đã giới thiệu với bạn cách xây dựng 1 Dependency Injection Container. Hi vọng từ bài viết này bạn có thể hiểu hơn về cách DI Container được xây dựng và hoạt động như thế nào. Nếu có thắc mắc và góp ý bạn comment phía dưới nhé. Cảm ơn bạn 😊

Tham khảo:

https://viblo.asia/p/laravel-beauty-tim-hieu-ve-service-container-3KbvZ1wLGmWB

https://viblo.asia/p/dependency-injection-hoat-dong-the-nao-trong-laravel-3Q75wD3JKWb

Chia sẻ bài viết ngay

Nguồn bài viết : Viblo