在這個 AI 大爆炸的一年,各種新名詞一個接著一個冒出來,像 vibe coding、AI pair programming……
現在如果不跟 AI 一起寫程式,反而比較少見哈哈。
畢竟這麼好用的工具都被發明出來了,我們要做的是學會善用它們,讓手上的開發又快又穩。
.
.
所以今天照慣例,請出我的共同開發夥伴 —— Claude Code CLI。
我們要做一個小但實用的功能:當使用者進入網站的產品頁時,讓畫面上的產品名稱自動加上「(全館優惠)」。
這個需求昨天已經用 Observer 走過一遍;今天換成 Plugin 的做法。
.
.
今天在開始實作之前,我們一樣先用快速介紹一下 Plugin——它是什麼、什麼時候該用;然後再請Claude協作把功能做出來。
Magento 的 Plugin,又叫做 攔截器(Interceptor),顧名思義,就是讓我們可以「在系統執行某個方法的時候,偷偷插一段自己的程式進去」。
它最大的特色是:不需要修改原始碼,就能改變 Magento 既有邏輯的輸入或輸出。你只要指定好:
這樣就可以寫出自己的邏輯,Magento 執行到那個方法時,就會自動把你的程式一起跑進去。
.
.
.
在 Magento Plugin 裡,有三種常見的「攔截點」:
攔截方式 | 執行時機 | 常見用途 |
---|---|---|
beforeX |
方法執行 之前 | 改參數 |
afterX |
方法執行 之後 | 改回傳值(最常用) |
aroundX |
方法被包起來 | 完全控制是否執行原方法 |
每一種都適用在不同情境:
// 攔截「呼叫前」:可以改參數
public function beforeFunctionName($subject, $name) {
return ['新參數']; // 要以 array 回傳所有參數
}
// 攔截「呼叫後」:可以改回傳值
public function afterFunctionName($subject, $result) {
return $result . '(全館優惠)';
}
// 攔截整段流程(使用起來比較複雜,可搭配claude去詳細了解)
public function aroundFunctionName($subject, \Closure $proceed) {
// ...你的邏輯
return $proceed(); // 要記得呼叫原方法
}
.
.
.
你只要在 di.xml
裡加上以下設定,就能對指定類別做攔截:
<type name="Magento\Catalog\Model\Product">
<plugin name="mrl_custom_plugin"
type="Mrl\PromoTag\Plugin\ProductNameTag"
sortOrder="10" />
</type>
上面這段意思是:「當系統呼叫 Magento\Catalog\Model\Product
這個類別的任何方法時,如果你在 ProductNameTag
裡寫了相對應的 beforeGetName()
或 afterGetName()
,就會被執行。」
.
.
⚠️ Plugin 只能攔 public 方法。
不能攔的包含:
__construct
、private
/protected
、final
、static
。
想改建構或初始化流程,請用 DI 注入(調整依賴)、Preference、或其他擴充點,而不是 Plugin。
.
.
.
如果你還是覺得 Plugin 有點抽象,沒關係,我們直接請 Claude 幫我們做一遍!
今天的任務很簡單:
幫我們做一個 Magento 2 小模組,當使用者進入產品頁時,在產品名稱後面自動加上「(全館優惠)」
請幫我建立一個 Magento 2 模組,當使用者進入產品頁(PDP)時,
在產品名稱後面加上「(全館優惠)」這段文字。
功能需求:
- 請使用 Plugin 方式
- 不要改資料庫,純顯示層
- 請幫我產生以下檔案:
- registration.php
- etc/module.xml
- etc/frontend/di.xml
- Plugin/ProductNameTag.php
claude開始幫我們生成,看過ok就可以按yes.
.
不到 3 分鐘,Claude 就幫我們生出完整的 Magento 模組結構:
這邊簡單講一下這些檔案是幹嘛的:
檔名 | 功能簡介 |
---|---|
registration.php |
告訴 Magento 這個模組的存在 |
module.xml |
定義模組名稱與版本(在安裝時用到) |
di.xml |
設定 Plugin 要攔截誰、用哪個類別來攔 |
ProductNameTag.php |
我們實際寫 Plugin 邏輯的地方 |
.
.
di.xml
怎麼註冊 Plugin
這段的意思就是:
當 Magento 執行 Magento\Catalog\Model\Product::getName() 時,請幫我也執行 ProductNameTag::afterGetName()!
我們可以看到:
Magento\Catalog\Model\Product
Mrl\PromoTag\Plugin\ProductNameTag
.
.
afterGetName()
這裡我們可以看到,我們攔截的是 getName()
這個方法,使用的是 afterGetName()
。
意思是:等原本的 function 執行完、拿到結果後(after),我們再進一步加工這個結果。
像這裡的例子,我們就是在原本的產品名稱後面,手動加上「(全館優惠)」這段文字,但原本的邏輯不會被改到。
這就是 after
插件的特色:安全、簡單,適合用來修改回傳值。
小補充:
在
afterGetName(Product $subject, $result)
裡,
$subject
是被攔截的原始物件,也就是Product
實體本身(你如果要存取其他屬性,也可以從這邊下手)$result
則是原本getName()
要回傳的值,也就是「原本的產品名稱」你只需要回傳加工過的
$result
,畫面上就會自動套用你的邏輯了
.
.
模組寫完後,我們還需要讓 Magento 認得它,記得下這幾行指令
php bin/magento module:enable Mrl_PromoTag
php bin/magento setup:upgrade
php bin/magento cache:flush
.
.
.
打開任一產品頁,你會發現產品名稱已經成功自動加上了「(全館優惠)」!
這代表 Plugin 完美發動,顯示層處理成功、資料庫沒被動到,乾淨俐落!
.
.
.
.
今天我們透過 Claude 的幫助,超快速完成了一個 Magento Plugin 小模組:
當使用者進入產品頁時,產品名稱後面會自動加上「(全館優惠)」這段字,簡單、實用、完全不動資料庫,效果馬上就能看到。
.
.
重點是整個開發過程——從需求、理解 Plugin 架構,到實際下 prompt、交給 AI 生成,再加上一點我們自己的調整 ——不到 10 分鐘,一個小功能就完成了
.
.
Plugin 是 Magento 裡非常實用的擴充方式,適合針對「特定方法」做修改,
而用 AI 來協助我們生成骨架、補程式,不只能加快速度,還能讓我們有更多時間專注在「功能怎麼設計」這件事上。
.
.
明天我們會繼續我們的AI 協作開發之旅,來認識 Magento 的第三種擴充方式 —— Preference。
我們會一起用最簡單的方式認識它,再用 Claude 直接實作一遍,照慣例輕鬆開發、順便踩個坑哈哈。