所有促銷排成一條 pipeline,順序寫死在同一個檔案裡。


電商做久了,促銷一定會變多。滿額折扣、滿額贈品、折扣碼、加價購、點數折抵、點數回饋⋯⋯每一種都會動到金額。

多數人的寫法是在 controller 或某個 CartService 裡面,一段一段 if 疊上去。疊到第五種的時候,沒有人敢動那個檔案了,因為你不知道把某段往上移三行會發生什麼事。

我的做法是:把每一筆促銷設定攤平成一個 stage,串成一條 pipeline,依序跑完。

public static function process(CartState $state, PromotionCatalog $promos): CartState
{
    return array_reduce(
        self::stages($promos),
        fn (CartState $carry, array $stage) => ($stage['apply'])($carry),
        $state,
    );
}

stages() 就是整條產線的排程表:

1. 滿額折扣階梯
2. 滿額禮(每一檔一個 stage)
3. 折扣碼
4. 加價購(每一檔一個 stage)
5. 點數回饋與折抵

注意兩件事。

第一,型別之間的順序是固定的、寫死的,就寫在這一個函式裡。行銷明天來問你「滿額折扣跟折扣碼是先折哪一個?兩個是相加還是連乘?」,你不用翻五個檔案,你打開這個檔案指給他看。這是我認為 pipeline 最大的價值——順序變成一份可以被閱讀、被討論的文件,而不是散落在 code 各處的隱性行為。

第二,同型別的多筆設定,各自是獨立的 stage。後台掛了三檔滿額禮,就攤平成三個 stage,每個 stage 只認自己那一筆設定。不需要在規則裡面寫迴圈,不需要判斷「我是第幾檔」。

每個 stage 我都帶一個 label:

$stages[] = [
    'label' => "滿額禮|滿 {$promo->threshold}",
    'apply' => fn (CartState $s) => PricingRules::thresholdGift($promo, $s),
];

這個 label 在開發階段非常好用。我可以做一個 debug 頁面,把每一個 stage 跑之前跟跑之後的狀態都印出來,一眼看出「金額是在哪一關變的、變了多少」。客服說「這張單為什麼只折 300?」,你把那筆購物車丟進去跑一次,答案就在畫面上。

促銷模組會一直長大,這是躲不掉的。你能做的,是讓它「長大的方式」很固定:新增一種促銷,就是新增一條規則、在 stages() 裡插一行。既有的規則一行都不用改。


⭐️ Shopify 網站開發服務(給品牌)
https://job.turn.tw/shopify-services

⭐️ 川川電商事務所(全客製電商開發服務)
https://chuanchuan.tw

⭐️ 台灣 Shopify 商家交流 LINE 群(非官方)
https://line.me/ti/g2/PZ_1LILWVWWuzZQ50HNpYA-A3k6QXWF6znqoBQ

⭐️ 台灣 Shopify 開發者 LINE 群(非官方)
https://line.me/ti/g2/YUasX5K3CJ4QdIx76zppjHlh3-q8w-xkSyK1LA

共有 0 則留言


⭐️ Shopify 網站開發服務(給品牌)
https://job.turn.tw/shopify-services

⭐️ 川川電商事務所(全客製電商開發服務)
https://chuanchuan.tw

⭐️ 台灣 Shopify 商家交流 LINE 群(非官方)
https://line.me/ti/g2/PZ_1LILWVWWuzZQ50HNpYA-A3k6QXWF6znqoBQ

⭐️ 台灣 Shopify 開發者 LINE 群(非官方)
https://line.me/ti/g2/YUasX5K3CJ4QdIx76zppjHlh3-q8w-xkSyK1LA
🏆 本月排行榜
🥇
站長阿川
📝45   💬1  
643
評分標準:發文×10 + 留言×3 + 獲讚×5 + 點讚×1 + 瀏覽數÷10
本數據每小時更新一次