Trong quá trình làm việc với Magento 2, chắc chắn có lúc bạn sẽ muốn thay đổi hoặc mở rộng một chức năng có sẵn của Magento phải không nào. Vậy có cách nào để bạn có thể làm được điều đó nhưng không ảnh hưởng đến phương thức gốc của Magento không nhỉ. Magento hỗ trợ nhiều cách để làm được điều này, trong bài viết này tôi sẽ hướng dẫn các bạn một cách đó là sử dụng Plugin trong Magento 2.
Plugin là một class có thể sửa đổi hành vi của bất cứ một phương thức public nào bằng cách chặn lệnh gọi tới phương thức ban đầu và thực hiện logic của bạn. Điều này cho phép bạn mở rộng thậm chí là ghi đè lên phương thức public ban đầu mà không làm ảnh hưởng đến phương thức đó.
Contents
Hạn chế của Plugin
Plugin không thể sử dụng được với các trường hợp sau:
- Class hoặc phương thức Final
- Phương thức không phải public
- Virtual types
- __construct
- Class hoặc phương thức static
Khai báo một Plugin
Để khai báo một Plugin bạn phải tạo file di.xml trong module của bạn. Ở đây tôi sử dụng module ViMagento_HelloWorld. Nếu bạn chưa cài đặt module các bạn có thể xem lại bài viết này. Các bạn tạo file ViMagento/HelloWorld/etc/di.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="{ObservedType}">
<plugin name="{pluginName}" type="{PluginClassName}" sortOrder="1" disabled="false"/>
</type>
</config>
Bạn phải xác định các thành phần sau:
- ObservedType: Một Class bạn muốn sửa đổi hoặc mở rộng
- pluginName: Tên của plugin của bạn nên đặt tên sao cho dễ hiểu, nói lên được chức năng plugin của bạn
- PluginClassName: Class plugin của bạn
- sortOrder: Thứ tự chạy của plugin. Số nhỏ sẽ chạy trước. Được sử dụng trong trường hợp có nhiều plugin tác động đến cùng một phương thức.
- disabled: Bật hoặc tắt plugin. True nếu bạn muốn tắt plugin. Mặc định là false
Quy ước đặt tên phương thức Plugin
Đầu tiên bạn cần xác định phương thức bạn muốn chỉnh sửa. Ví dụ ở đây tôi muốn chỉnh sửa phương thức getTitle()
...
public function getTitle($title)
{
...
}
...
Để chỉnh sửa phương thức getTitle, bạn cần tạo các phương thức sau:
- beforeGetTitle
- aroundGetTitle
- afterGetTitle
Cũng đơn giản đúng không nào. Việc bạn cần làm đó là viết hoa chữ cái đầu của tên phương thức mà bạn muốn sửa đổi. Trường hợp phương thức có ‘_’ như _getTitle chẳng hạn thì bạn không cần viết hoa chữ cái đầu nữa. Ví dụ:
- before_getTitle
- around_getTitle
- after_getTitle
Phương thức before
Nghe tên thì các bạn cũng có thể đoán được cách nó hoạt động rồi đúng không nào. Phương thức before sẽ chạy trước phương thức mà nó sẽ tác động đến. Tên của nó phải trùng với tên của phương thức gốc và có tiền tố before ở phía trước. Ví dụ: beforeGetTitle
Bạn có thể sử dụng phương thức before đế thay đổi đối số đầu vào của phương thức gốc bằng cách trả về đối số đã sửa đổi. Nếu có nhiều hơn một đối số thì phương thức sẽ trả về một mảng các đối số. Còn nếu không có sửa đổi gì hãy trả về một giá trị null.
<?php
namespace ViMagentoHelloWorldPlugin;
class UpdateProductName
{
public function beforeSetName(MagentoCatalogModelProduct $subject, $name)
{
$name = "HelloWorld";
return [$name];
}
}
Ở ví dụ trên tôi đã sửa đổi đối số $name thành dòng chữ HelloWorld và trả về cho phương thức gốc xử lý bằng phương thức before.
Phương thức after
Ngược lại với before phương thức after sẽ được chạy sau khi phương thức gốc đã chạy xong. Phương thức này bắt buộc phải có giá trị trả về và phải có tên trùng với phương thức gốc với tiền tố là after. Chúng ta có thể sử dụng phương thức after để thay đổi kết quả trả về của phương thức ban đầu bằng cách thay đổi nó và trả về giá trị đã thay đổi ở cuối phương thức.
<?php
namespace ViMagentoHelloWorldPlugin;
class UpdateProductName
{
public function afterGetName(MagentoCatalogModelProduct $subject, $result)
{
$result = "HelloWorld";
return $result;
}
}
Ở ví dụ trên tôi đã thay đổi kết quả trả về bằng dòng chữ HelloWorld. Sau khi phương thức getName thực hiện xong nó sẽ truyền kết quả trả về ($result) và các đối số cho phương thức tiếp theo xử lý, ở đây là phương thức afterGetName của chúng ta.
Phương thức around
Phương thức around sẽ chạy trước và sau phương thức ban đầu. Nó cho phép bạn có thể sửa đối số đầu vào, kết quả trả về và thậm chí ghi đè lên phương thức ban đầu. Phương thức around phải có tên trùng với phương thức ban đầu và có tiền tố around.
Phương thức around có một điểm đặc biệt đó là callable. Nó sẽ nhận một callable có thể gọi đến phương thức tiếp theo trong chuỗi hoặc phương thức ban đầu. Nếu callable không được gọi thì tất cả các phương thức tiếp theo trong chuỗi sẽ không chạy.
<?php
namespace MyModulePlugin;
class ProductAttributesUpdater
{
public function aroundSave(MagentoCatalogModelProduct $subject, callable $proceed)
{
$someValue = $this->doSmthBeforeProductIsSaved();
$returnValue = null;
if ($this->canCallProceedCallable($someValue)) {
$returnValue = $proceed();
}
if ($returnValue) {
$this->postProductToFacebook();
}
return $returnValue;
}
}
Ở ví dụ trên các bạn để ý sẽ thấy $returnValue = $proceed() đoạn này sẽ gọi đến phương thức tiếp theo trong chuỗi. Ví dụ có nhiều plugin cùng tác động đến phương thức save ở trên thì các plugin có thuộc tính sortOrder nhỏ sẽ chạy trước. Khi nó gọi đến callable $proceed đồng nghĩa với việc gọi đến plugin tiếp theo trong chuỗi. Còn nếu bạn không gọi $proceed thì tất cả phương thức phía sau sẽ không được chạy.
Kết luận
Tóm lại plugin có thể thay đổi hành vi của các function public. Cả ba phương thức đều có đối số đầu tiên là $subject để cung cấp quyền truy cập vào tất cả các phương thức public có trong $subject. Và plugin có ba loại:
- before: Thay đổi đối số đầu vào
- after: Thay đổi kết quả trả về
- around: có thể thay đổi đối số đầu vào, kết quả trả về và ghi đè lên phương thức gốc.
Trường hợp có nhiều plugin cùng tác động lên một phương thức thì thứ tự của plugin chạy theo thuộc tính sortOrder. Nhưng nếu không có thuộc tính sortOrder thì nó sẽ chạy theo thứ tự load của module nhé. Để xem thứ tự load của module các bạn có thể xem trong file app/etc/config.php
Bài viết này chúng ta đã cùng nhau tìm hiểu cách sử dụng plugin cơ bản trong Magento 2, trong bài tiếp theo tôi sẽ hướng dẫn các bạn cách thay đổi tên của sản phẩm sử dụng plugin để các bạn có được cái nhìn tổng quan hơn về plugin trong Magento 2 hoạt động như thế nào nhé !
Tài liệu để các bạn tham khảo thêm: https://devdocs.magento.com/guides/v2.4/extension-dev-guide/plugins.html