Magento 2 không còn mới đối với các developer Việt Nam nữa. Hầu hết các developer yêu thích Magento 2 bởi vì công nghệ phong phú của nó. Dependency Injection (DI) là một trong những design patterns mà Magento 2 sử dụng nhưng nhiều người vẫn chưa hiểu chính xác DI là gì? Vì vậy tôi sẽ cố gắng giải thích DI một các dễ hiểu nhất có thể trong bài viết này.

Giới thiệu
Như cái tên của nó đã nói, Các bạn hãy hiểu riêng biệt từng từ của DI:
Dependency
Dependency có nghĩa đơn giản là một cái gì đó phụ thuộc vào một cái gì đó, giống như bạn đang phụ thuộc vào ba mẹ của bạn vậy. Trong lập trình bạn cũng có thể hiểu tương tự như vậy, một class sẽ phụ thuộc vào các Object được khởi tạo bên trong class đó. Ví dụ:
1 2 3 4 5 6 7 8 9 10 |
<?php class Product { public function getTax($id) { $tax = new Taxation(); return $tax->getCalculateTax($id); } } |
Ở đoạn code trên bạn có thể thấy class Product có một phương thức getTax và bên trong khởi tạo một đối tượng Taxation với từ khóa new. Đây là một cách khởi tạo trong lập trình hướng đối tượng. Bạn nghĩ sao nếu không tìm thấy class Taxation? Tất nhiên là class Product sẽ không hoạt động được. Vậy ở đây ta sẽ nói class Product phụ thuộc vào đối tượng Taxation bởi vì nó không thể hoạt động đúng nếu không tìm thấy đối tượng Taxation. Trong Magento 2 sự phụ thuộc có thể là một class sử dụng Model hoặc một class của một Module khác chẳng hạn.
Injection
Injection đơn giản có nghĩa là cung cấp một cái gì đó bởi bên thứ ba.
Và ở ví dụ trên, new Taxation() là đối tượng cần cung cấp bởi bên thứ 3.
Vì vậy Dependency Injection là loại bỏ việc phụ thuộc trực tiếp của class với đối tượng, thay vào đó sẽ sử dụng một bên thứ 3 để tạo các đối tượng cho class đó là Object Manager trong Magento 2.
Tại sao lại phải sử dụng Dependency Injection?
Bạn vẫn chưa hiểu tại sao phải sử dụng Dependency Injection? Giả sử bạn cần xây dựng một ngôi nhà, Bạn sẽ làm gì? Điều bạn cần cơ bản khi bắt đầu là gạch và xi măng…Vậy bạn sẽ bắt đầu đi tìm đất sét để làm gạch và sau đó xây nhà? Hay bạn sẽ mua gạch tại một nhà cung cấp và chỉ việc xây nhà thôi.
Điều đó hoàn toàn đúng, bạn chỉ cần liên hệ với nhà cung cấp gạch và mọi thứ sẽ sẵn sàng để bạn xây dựng căn nhà của mình. Đó cũng là những gì Dependency Injection sẽ làm. Nó sẽ tách class của bạn khỏi việc xây dựng phụ thuộc của nó.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
class Customer { private $firstName; private $lastName; public function __construct($firstName, $lastName) { $this->firstName = $firstName; $this->lastName = $lastName; } public function getFirstName() { return $this->firstName; } public function getLastName() { return $this->lastName; } } class CustomerInfo { private $customer; public function __construct($customerFirstName, $customerLastName) { $this->customer = new Customer($customerFirstName, $customerLastName); } public function getCustomer() { return $this->customer; } } |
Chẳng có gì sai đối với đoạn code trên. Nó sẽ trả về firstname và lastname mà chẳng gặp vấn đề gì cả. Nhưng vấn đề ở đây là class Customer được liên kết chặt chẽ với class CustomerInfo. Nếu class Customer có cập nhật chẳng hạn như thêm một tham số email chẳng hạn. Và sau đó những nơi có khởi tạo đối tượng Customer bạn phải sửa đổi và truyền thêm vào một đối số là email. Mọi chuyện vẫn ổn nếu chỉ có một chỗ khởi tạo đối tượng Customer nhưng không may bạn tham gia một dự án lớn và có hàng trăm chỗ có khởi tạo đối tượng Customer. Chỉ nghe thôi cũng đã cảm thấy tồi tệ rồi ý nhỉ.
Đến đây thì các bạn cũng có thể hiểu được lợi ích và tại sao phải sử dụng Dependency Injection rồi phải không nào. Dependency Injection sẽ giải quyết được vấn đề trên bằng cách truyền các phụ thuộc vào phương thức Constructor của class.
Cách sử dụng Dependency Injection
Và đây là cách mà Dependency Injection làm việc:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<?php class Product { protected $_taxation; public function __construct( \Taxation $taxation ) { $this->_taxation = $taxation; } public function getTax($id) { return $this->_taxation->getCalculateTax($id); } } |
Trong đoạn code trên bạn có thể thấy, chúng ta không sử dụng từ khóa new để khởi tạo class Taxation. Nhưng có thể bạn sẽ nghĩ trong trường hợp class Taxation không có tham số truyền vào thì vẫn ổn nhưng nếu class có tham số truyền vào thì sao nhỉ. Chúng ta sẽ truyền tham số cho class Taxation bằng cách nào. Đây cũng là một điều mà Magento 2 Dependency Injection đã làm rất tốt.
Để giải quyết tình huống trên đó là truyền tham số cho một phụ thuộc, tất cả những gì bạn cần làm là tạo một file di.xml trong module của bạn.
1 2 3 4 5 |
<type name="/Taxation"> <arguments> <argument name="firstname" xsi:type="string">Nguyễn Văn Tèo</argument> </arguments> </type> |
Điều này có nghĩa là khi Object Manager tạo đối tượng Taxation nó sẽ kiểm tra khai báo trong file di.xml và thêm giá trị Nguyễn Văn Tèo vào biến firstname với kiểu giá trị là string. Bạn có thể thêm bất kỳ kiểu giá trị nào vào xsi:type như string, object, int…Đây cũng là lý do mà tôi khuyên bạn nên sử dụng Dependency Injection thay vì sử dụng phương thức create() của Object Manager để khởi tạo đối tượng. Vì sử dụng phương thức create() của Object Manager bạn sẽ không truyền tham số được cho những phụ thuộc của class.
Kết luận
Bằng cách hiểu những gì đã được viết ở trên bạn có thể nắm được cơ bản về Dependency Injection trong Magento 2. Hy vọng bài viết có thể giúp được phần nào cho các bạn. Nếu các bạn có thắc mắc gì liên quan đến Dependency Injection trong Magento 2 các bạn có thể để lại bình luận bên dưới để được giải đáp.
Nên đọc thêm về SOLID