iT邦幫忙

2025 iThome 鐵人賽

DAY 10
1
Software Development

《電商修仙術:AI × Magento 開發心法》系列 第 10

[Day 10] 什麼!? AI 3分鐘幫我寫好 Magento 模組? - Preference 篇

  • 分享至 

  • xImage
  •  

前言

還記得昨天我們用 Plugin,請 Claude 幫我們快速做出一個「進入產品頁 → 產品名稱後面自動加上(全館優惠)」的小功能嗎?

那次我們用到的,是 Magento 最常用、也最安全的一種擴充方式:Plugin 攔截器
不過在 Magento 裡,還有另一種威力更強大的做法:Preference

顧名思義,Preference 就是「優先權」——當系統要用某個 class 的時候,我們可以偷偷指定:「欸,別用原本的,用我的!」

今天,我們就來用 Preference 實戰一次,繼續體驗 AI 協作開發的威力。

.
.


快速認識 Preference 是什麼?

Preference = 完整替換某個類別的實作

Magento 本身有很多核心 class,例如 Magento\Catalog\Model\Product
.
.
如果我們寫一個 Preference,指向我們自訂的 class,那麼以後系統只要用到 Product,都會自動換成我們的版本。
.
.
這聽起來是不是很暴力?因為它真的是一刀切——你說換掉,它就真的整個換掉。
所以 Preference 的特色是:

  • ✅ 可以完全掌控某個 class 的邏輯
  • ⚠️ 但風險也很高,因為一換就是整個換掉,其他人寫的 Plugin 可能就沒機會生效了

.
.


Preference 設定怎麼寫?

你只需要在 di.xml 裡下這一段:

<preference for="Magento\Catalog\Model\Product"
            type="Mrl\PromoTag\Model\Product" />

意思就是:

當系統想要用 Magento\Catalog\Model\Product 時,請改用 Mrl\PromoTag\Model\Product(你開發實用的class) 這個 class。

.
.
.


適合使用 Preference 的時機是?

Preference 最適合用在 你需要全面掌控某個 class 的邏輯,或者 你想修改的是 Plugin 無法攔截的地方,例如 private 方法、protected 方法、建構子(__construct)等等。
這些情境下,Plugin 是無能為力的,只有 Preference 能幫你達成目的。
.
.
不過要特別注意的是:Preference 的影響範圍非常大,因為它會直接替換掉原本的 class,導致其他人針對這個 class 所寫的 Plugin 通通不會被執行。這不只可能踩雷,也可能讓你的擴充無意間破壞系統其他邏輯。
.
.
一句話總結:當你需要改的是 Plugin 無法觸及的地方,或你真的需要完全接管某個類別的邏輯時,就該出動 Preference。

.
.
.


AI 協作實戰:用 Preference 改產品名稱

說了這麼多不如直接來做,現在就讓我們實戰了解 Preference!
這次一樣請出我的好夥伴 —— Claude Code CLI。

我們只要把需求整理好,丟給它,它就會幫我們產生整包模組。Let's go!

今天我們要做的需求一樣簡單:

幫我們做一個 Magento 2 小模組,進入產品頁時,把產品名稱自動加上「(全館優惠)」。

不過這次我們不走 Plugin,而是:
直接用 Preference,把 Product 類別換掉,覆寫它的 getName()
.
.


我下給 Claude 的 prompt:

請幫我建立一個 Magento 2 模組,
需求:當使用者進入產品頁(PDP)時,
在產品名稱後面加上「(全館優惠)」。

功能需求:
- 請使用 Preference 方式
- 不要改資料庫,純顯示層
- 請幫我產生以下檔案:
  - registration.php
  - etc/module.xml
  - etc/frontend/di.xml
  - Model/Product.php (繼承原本的 Product 並改寫 getName())

https://ithelp.ithome.com.tw/upload/images/20250910/201784039dqVxzAsmd.png

.
.

生成完成!
https://ithelp.ithome.com.tw/upload/images/20250910/20178403yRxVqSSo63.png

.
.

接下來我們來看看claude幫我們生成的檔案

https://ithelp.ithome.com.tw/upload/images/20250910/20178403saAm08EoDw.png
這裡可以看到:

  • registration.php:讓 Magento 知道這是個新模組
  • etc/module.xml:定義模組名稱和版本
  • etc/frontend/di.xml:設定 Preference 的接管
  • Model/Product.php:我們實作 getName() 的地方,也就是整個功能的核心
    .
    .

接著看一下 di.xml 怎麼註冊 Preference

這次我們用的是 Preference,所以 di.xml 裡的設定會長這樣:

https://ithelp.ithome.com.tw/upload/images/20250910/20178403MY2c3OovYb.png
這段的意思是:

當 Magento 嘗試載入 Magento\Catalog\Model\Product 這個 class 時,請改用我們自己寫的 Mrl\PromoNameSuffix\Model\Product!

跟 Plugin 不一樣的是,這裡我們沒有攔截某個特定的方法,而是整個 class 都被我們接管了
之後系統裡所有用到 Product 的地方,都會自動轉向我們的版本。
.
.


關鍵程式:Product.php

接下來看到我們指定接管class的地方:

https://ithelp.ithome.com.tw/upload/images/20250910/20178403Wefm9dJvka.png

這裡我們做了什麼?

  1. 繼承 Magento 原本的 Product 類別
  2. 改寫(override)了 getName() 方法
  3. 在回傳值後面加上「(全館優惠)」

小提醒:因為我們是繼承原本的 Product,所以其他功能(像是價格、描述、庫存等方法)都不用自己再重寫,會自動沿用原本的邏輯。

只要改寫你需要客製的那幾個方法就好!

這樣一來,系統裡只要呼叫 getName() 的地方,都會自動使用我們這個版本,名稱也就會自動加上我們指定的後綴文字啦!
.
.


別忘了啟用模組

寫完後記得輸入:

php bin/magento module:enable Mrl_PromoTag
php bin/magento setup:upgrade
php bin/magento cache:flush

.
.


成果驗收

一樣打開產品頁,名稱後面已經自動加上了「(全館優惠)」!

這次不靠 Plugin,而是靠 Preference 的強制覆寫,效果一樣直接生效。

https://ithelp.ithome.com.tw/upload/images/20250910/20178403Q76Z1ecMFb.png

.
.
.


結語

走到這裡,我們已經實作過 Magento 最常見的三種擴充方式:

  • Plugin(攔截方法,最安全也最常見)
  • Observer(針對事件處理,鬆耦合的好幫手)
  • Preference(整個 class 換掉,掌控力最強,但也最危險)

.
.
一路實作下來,我開始慢慢抓到它們之間的差異,也更清楚什麼時候該出哪一招。
每一種擴充方式就像三種武功——各有特性,各有代價,用得好就能事半功倍。
.
.
到現在為止,我們已經漸漸掌握住 Magento 後端開發的精髓了。
請繼續跟上我們的旅程,接下來——我們即將進入更完整的實戰!


上一篇
[Day 9] 什麼!? AI 3分鐘幫我寫好 Plugin 模組?
下一篇
[Day 11] 什麼!? AI 3 分鐘幫我寫好 Magento 模組?— system.xml 後台設定篇
系列文
《電商修仙術:AI × Magento 開發心法》11
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言