購物車存的是「客戶做了什麼選擇」,不是「算出來多少錢」。


我看過很多購物車,session 裡面長這樣:

items、subtotal、discount、shipping_fee、total、free_shipping、gift_name ...

金額被寫進 session,然後系統到處讀它。這種寫法上線之後一定會出事。因為金額是「算出來的東西」,它會過期。商品改價了、活動檔期結束了、折扣碼被停用了,session 裡那份數字卻還活著。客戶放著購物車三天沒動,回來結帳,看到的是三天前的價格。

我的做法是:session 只存客戶的原始輸入。

items    sku => 數量
coupon   折扣碼
addons   sku => 數量(加價購勾選)
points   想折抵的點數
note     訂單備註

就這五個欄位,全部都是「客戶按了什麼」,沒有任何一個是算出來的。

金額呢?每次要顯示、每次要結帳,都從這份輸入重新撈 DB、重新跑一次計價,從頭算到尾。不保留任何上一次的計算結果。

這件事聽起來很浪費,但實際上它解決了電商最麻煩的一整類 bug:購物車頁顯示的金額,跟結帳當下算出來的金額不一致。因為兩邊跑的是同一段程式、吃的是同一份輸入,它們不可能不一致。

再進一步,我會把這份輸入包成一個 immutable 的 CartInput:

Session Array ──fromSession──▶ CartInput
CartInput ──addItem / removeItem / withCoupon / addAddOn──▶ CartInput
CartInput ──toSession──▶ Session Array

每個操作都不改原本的物件,而是回傳一個新的 CartInput。Controller 的每個 action 就變成三行:讀出來、變形、存回去。

這樣做還有一個好處:購物車的「不變條件」可以直接寫在建構子裡,強制執行。

例如我的規則是「加價購不能單獨存在」。客戶如果加了一件商品、勾了加價購,然後把正常商品刪光,加價購就應該一起清掉,不然他會用加購價單買加購品。

這條規則我不寫在 controller,我寫在 CartInput 的建構子:沒有正常商品時,加購、點數、備註一律清空。因為所有變更方法都會經過建構子,所以 session 永遠是合法、自洽的,不會出現「session 裡有、計算時卻被忽略」這種鬼狀態。

購物車 session 的規格,一句話就講完了:只存意圖,金額每次重算。


⭐️ 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
本數據每小時更新一次