Như bạn biết thì Magento sử dụng mô hình dependency injection để khai báo các phụ thuộc. Tuy nhiên constructor injection sẽ sinh ra các phụ thuộc dây chuyền khi bạn tạo một đối tượng. (Đối tượng ban đầu sẽ có các phụ thuộc và các phụ thuộc đó lại có các phụ thuộc khác nữa). Trong bài viết này mình sẽ giới thiệu với các bạn một phương pháp hiệu quả để tối ưu code hơn. Đó là Magento 2 proxy.
Magento’s constructor injection pattern enables you to flexibly manage your class dependencies. However, constructor injection also means that a chain reaction of object instantiation is often the result when you create an object. (The original object has dependencies that have dependencies, and those objects have dependencies, and so on.)
Nếu constructor của một class sử dụng nhiều tài nguyên, điều này có thể ảnh hưởng đến hiệu xuất cho các class phụ thuộc vào nó. Vì sẽ có các đối tượng bị dư thừa, hay nói cách khác là sẽ có một số đối tượng không cần dùng đến cho các request cụ thể.
Bạn có thể bật profiling để xem được danh sách dependency(phụ thuộc) của class.
Ví dụ, hãy xem hai class sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
class FastLoading { protected $slowLoading; public function __construct( SlowLoading $slowLoading ){ $this->slowLoading = $slowLoading; } public function getFastValue() { return 'FastLoading value'; } public function getSlowValue() { return $this->slowLoading->getValue(); } } |
Giả sử rằng class SlowLoading
có ảnh hưởng không nhỏ đến hiệu suất khi được khởi tạo (có thể do truy vấn cơ sở dữ liệu phức tạp hoặc lệnh gọi đến API web của bên thứ ba). Do class FastLoading
sử dụng dependency injection constructor, nên việc gây ảnh hưởng đến hiệu suất sẽ phát sinh khi FastLoading
được khởi tạo. Nhưng class SlowLoading
chỉ được sử dụng trong method getSlowValue
. Điều này có nghĩa rằng sẽ không cần thiết nếu method này không được gọi trong đối tượng FastLoading
. Ví dụ sẽ có request bạn không cần dùng đến method này, điều này dẫn đến ảnh hưởng lớn đến hiệu suất của trang web.
Proxy trong Magento 2
Magento sử dụng proxy để giải quyết vấn đề trên.
Proxies extend other classes to become lazy-loaded versions of them. That is, a real instance of the class a proxy extends is created only after one of the class’s methods is actually called.
Một đối tượng chỉ được khởi tạo khi mà 1 trong các method của nó được gọi. Một proxy sẽ có các đặc tính giống như class gốc, vì thế nó có thể được gọi bất cứ nơi nào mà class gốc có thể. Không giống với class gốc, proxy chỉ có 1 phụ thuộc, đó là object manager.
Magento sẽ tự động tạo class proxy này nên bạn không cần tạo nó theo cách thủ công. Bạn chỉ cần khai báo nó theo định dạng \Original\Class\Name\Proxy
và Magento sẽ tạo class này nếu nó chưa tồn tại.
Sử dụng ví dụ ở đầu bài viết, một proxy có thể được truyền vào constructor thay cho class gốc, sử dụng DI để làm điều đó:
1 2 3 4 5 |
<type name="FastLoading"> <arguments> <argument name="slowLoading" xsi:type="object">SlowLoading\Proxy</argument> </arguments> </type> |
Sử dụng proxy thay thế cho SlowLoading
nên SlowLoading
sẽ không được khởi tạo, cho đến khi có 1 method trong SlowLoading
được gọi.
Ví dụ về proxy trong Magento 2
Các bạn có thể xem trong vendor/magento/module-store/etc/di.xml
1 2 3 4 5 |
<type name="Magento\Store\Model\Resolver\Website"> <arguments> <argument name="storeManager" xsi:type="object">Magento\Store\Model\StoreManagerInterface\Proxy</argument> </arguments> </type> |
Đoạn code trên, có nghĩa rằng sẽ sử dụng proxy thay thế cho class Magento\Store\Model\StoreManagerInterface
.
Ở trên ta đã truyền object Magento\Store\Model\StoreManagerInterface\Proxy
với tên biến là $storeManager
.
Sau đó việc gọi dependency thì chỉ việc làm như bình thường:vendor/magento/module-store/Model/Resolver/Website.php
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<em>/** * </em><strong><em>@var </em></strong><em>\Magento\Store\Model\StoreManagerInterface */ </em>protected $_storeManager; <em>/** * </em><strong><em>@param </em></strong><em>\Magento\Store\Model\StoreManagerInterface $storeManager */ </em>public function __construct( \Magento\Store\Model\StoreManagerInterface $storeManager ) { $this->_storeManager = $storeManager; } |
Bài viết liên quan
Tham khảo: https://devdocs.magento.com/guides/v2.4/extension-dev-guide/proxies.html
Cảm ơn tác giả