外觀
Woodmart-Child Theme 架構說明文件
版本:交接版(2026-04-29) 適用對象:接手本網站的開發團隊 前置知識:WordPress、WooCommerce、PHP、jQuery、基礎 Linux/SSH
目錄
1. 導讀與適用對象
本文件提供 woodmart-child 子主題的完整導覽。本網站是一個台灣 WooCommerce 電商,主要客製化集中在:
- 台灣金流整合:藍新金流(NewebPay,含超商取貨付款 CVSCOM)、LINE Pay
- 結帳流程:台灣地址 vs 國際地址雙路徑、運送方式條件式顯示欄位
- 訂單狀態管理:尤其是超商取貨付款的兩段式狀態流程(選店 → 取貨付款)
⚠️ 最易出錯的區域:藍新超商取貨整合(
functions.php第 1670–2397 行),約佔全檔 1/3,務必仔細閱讀第 5 章「台灣金流流程圖」。
2. Theme 整體架構
Parent / Child Theme 關係
wp-content/themes/
├── woodmart/ ← 父主題(v7.2.5,購買自 ThemeForest)
│ 禁止直接編輯。父主題會被升級覆蓋。
└── woodmart-child/ ← 子主題(本專案的開發主場)
所有客製化都在這裡。- 為什麼用 child theme:父主題未來會升級,若直接改父主題,升級後客製會全部消失。
- 載入順序:WordPress 自動先載
woodmart,再載woodmart-child,後者可覆寫前者的樣式與模板。 - JS/CSS 優先級:子主題使用
wp_enqueue_scriptspriority 1000(最後載入),確保覆蓋父主題樣式。
子主題的三大覆寫機制
| 機制 | 路徑 | 用途 |
|---|---|---|
| 函式覆寫 | functions.php | 透過 hook 改變父主題或外掛行為 |
| 樣式覆寫 | style.css | 覆蓋父主題 CSS |
| 模板覆寫 | woocommerce/、ultimate-member/ | 整支模板替換(同名同路徑即覆寫) |
3. 目錄結構地圖
woodmart-child/
├── functions.php ★ 主要客製檔(2397 行,第 4 章詳述)
├── style.css 自訂 CSS
├── header.php 覆寫父主題 header
├── footer.php 覆寫父主題 footer(含追蹤碼、客服按鈕等)
├── screenshot.png 主題縮圖(後台主題列表用)
│
├── js/
│ ├── main.js ← 開發時編輯這個
│ └── main.min.js ← 上線載入這個(修改 main.js 後必須 minify)
│
├── header-elements/ 自訂 header 元件(透過 Woodmart options 嵌入)
│ ├── cart.php 購物車 widget
│ └── column.php 自訂欄位元件
│
├── woocommerce/ ★ WooCommerce 模板覆寫
│ ├── single-product.php 單一商品頁
│ ├── emails/ 自訂訂單通知 email
│ └── myaccount/ 會員中心客製
│
├── ultimate-member/ Ultimate Member 外掛模板覆寫(會員系統)
│
├── img/ 主題圖片資源(icon、社群圖示等)
│
└── CSS backup/ ★ 可忽略:早期 CSS 備份,與生產環境無關js/main.js ↔ main.min.js 同步流程
WordPress 載入的是 main.min.js(壓縮版)。修改 main.js 後,務必執行:
bash
uglifyjs wp-content/themes/woodmart-child/js/main.js \
-o wp-content/themes/woodmart-child/js/main.min.js版本號自動由
filemtime()帶入,無須手動 bump(見模組 A)。
4. functions.php 模組總覽
functions.php 共 2397 行、約 80+ 個函式/Hook。下表依功能分類,並列出起始行號,方便定位。詳細的逐函式說明見 functions.php.txt。
| 模組 | 行號區間 | 主題 | 重要程度 |
|---|---|---|---|
| A | 1–58 | 資產載入、版本控制、編輯器字型 | ⭐⭐ |
| B | 60–86 | WooCommerce 運費邏輯(免運顯示規則) | ⭐⭐⭐ |
| C | 88–150 | 訂單詳情頁追蹤(GA4 purchase event、affiliate) | ⭐⭐ |
| D | 152–278 | 藍新超商取貨訂單狀態管理(核心) | ⭐⭐⭐⭐⭐ |
| E | 280–328 | 後台訂單列表「需出貨」欄位 | ⭐⭐ |
| F | 330–490 | 前端最佳化(emoji/embed 移除、jQuery migrate 移除、DNS prefetch、defer) | ⭐ |
| G | 492–727 | 結帳欄位客製(地址、運送方式條件式顯示、台灣 vs 國際雙路徑) | ⭐⭐⭐⭐ |
| H | 729–770 | 6H 配送注意事項彈窗 | ⭐⭐ |
| I | 772–838 | 追蹤碼(LINE Tag、FB 域名驗證、GTM) | ⭐⭐⭐ |
| J | 840–1144 | 覆寫父主題 woodmart_page_title(),加入 breadcrumbs | ⭐⭐⭐ |
| K | 1147–1212 | 訂單滯留檢查(目前停用,保留作未來啟用參考) | ⭐ |
| L | 1214–1262 | AddToAny LINE 好友、優惠券 email 限制修正 | ⭐⭐ |
| M | 1264–1279 | SEO:英文網址 noindex(/en_us/) | ⭐⭐ |
| N | 1281–1337 | LINE Pay 訂單狀態異常自動修復(5 分鐘後重檢 + 寄信通知) | ⭐⭐⭐⭐ |
| O | 1339–1377 | 結帳性別欄位儲存與預設值 | ⭐⭐ |
| P | 1379–1408 | Yoast SEO robots.txt 修正、Advanced Order Export 開放自訂 PHP | ⭐ |
| Q | 1410–1482 | 學生角色機制(st- 優惠券觸發、季度 cron 清除過期) | ⭐⭐⭐ |
| R | 1484–1597 | GPT 問答 shortcode + AJAX + 自訂資料表 wp_gpt_answers | ⭐⭐⭐ |
| S | 1599–1667 | 相關商品排除 no-show 分類 | ⭐⭐ |
| T | 1669–1802 | 自訂超商取貨運送方式類別 WC_Custom_CVSCOM_Shipping_Method | ⭐⭐⭐⭐⭐ |
| U | 1804–2152 | 藍新 × 運送方式整合 JS(最複雜) | ⭐⭐⭐⭐⭐ |
| V | 2154–2175 | 後端阻擋 LINE Pay + 超商取貨組合 | ⭐⭐⭐⭐ |
| W | 2177–2271 | 藍新付款參數補正(receipt 頁攔截) | ⭐⭐⭐⭐⭐ |
| X | 2273–2372 | 動態關閉藍新外掛超商取貨設定(option filter 攔截) | ⭐⭐⭐⭐⭐ |
| Y | 2374–2397 | 藍新自動跳轉時間調整(10s → 3s) | ⭐⭐ |
模組 D、T、U、V、W、X 共同構成「藍新超商取貨完整整合」,請務必合在一起閱讀。
5. 台灣金流流程圖(重點章節)
5.1 藍新金流超商取貨完整流程
藍新超商取貨有兩種付款模式:
| 模式 | 藍新代號 | _nwpSelectedPayment | _CVSCOMNotPayed | 說明 |
|---|---|---|---|---|
| 超商取貨付款 | CVSCOM=2 | CVSCOMPayed | 0 | 顧客到超商取貨時才付錢(貨到付款) |
| 超商取貨不付款 | CVSCOM=1 | Credit 或其他 | 1 | 線上先付款,到超商只取貨 |
完整流程(以「超商取貨付款 / CVSCOM=2」為例)
[1] 顧客在購物車選「超商取貨」運送方式
│
│ → JS(模組 G、U)動態:
│ - 隱藏地址欄位
│ - 顯示藍新外掛的「nwp_selected_payments」下拉
│ - 顯示 #CVSCOMNotPayed checkbox(視覺隱藏但保留 DOM)
│ - 隱藏 LINE Pay 付款選項
│
[2] 顧客選擇「超商取貨付款」(nwp_selected_payments = CVSCOMPayed)
│
│ → JS autoToggleCheckbox():CVSCOMNotPayed = unchecked (=0)
│
[3] 顧客填妥資料,按「結帳」
│
│ → 後端 woocommerce_after_checkout_validation
│ ├─ prevent_linepay_with_store_pickup(模組 V):擋掉 LINE Pay+超商
│ └─ newebpay_handle_non_cvscom_shipping(模組 W 上半):清資料
│
│ → WooCommerce 建立訂單 → 進入 receipt 頁面
│
[4] receipt 頁渲染前 newebpay_intercept_before_payment_page(模組 W):
│ ├─ 確認運送=超商 + 付款=CVSCOMPayed
│ └─ 補正 _CVSCOMNotPayed = 0
│
│ → option_woocommerce_newebpay_settings filter(模組 X):
│ └─ 動態決定外掛是否啟用 CVSCOMPayed/CVSCOMNotPayed 設定
│
[5] 藍新外掛產生加密表單,3 秒後自動 POST 至藍新(模組 Y)
│
[6] 藍新導向「選擇門市」頁面 → 顧客選店 → 回傳第一次 callback
│
│ → WooCommerce 訂單狀態被外掛改為 processing/completed
│ → ❗ newebpay_cvscom_fix_status(模組 D)攔截:
│ 檢查訂單備註,若只有「店家:」沒有「付款時間」
│ → 強制改回 pending(等待顧客取貨付款)
│
[7] 顧客到超商取貨並付款 → 藍新回傳第二次 callback(含「付款時間」)
│
│ → 訂單備註出現「藍新金流交易序號 + 付款時間」
│ → newebpay_cvscom_fix_status 此時不攔截,狀態 = completed ✅關鍵函式速查(藍新整合)
| 函式 | 行號 | 觸發時機 | 用途 |
|---|---|---|---|
WC_Custom_CVSCOM_Shipping_Method | 1681 | WC 載入運送方式 | 註冊「超商取貨」運送方式 |
add_custom_cvscom_shipping_method | 1799 | woocommerce_shipping_methods | 將上述類別加入 WC |
my_hide_shipping_when_free_is_available | 62 | 計算運費時 | 免運時仍顯示超商取貨、6H |
custom_checkout_field_script | 515 | wp_footer(結帳) | 條件式顯示地址欄位 |
wps_select_checkout_field_process | 671 | woocommerce_checkout_process | 後端驗證地址欄位 |
newebpay_shipping_payment_integration | 1816 | wp_footer(結帳) | 超商 × 付款方式整合 JS(最重要) |
prevent_linepay_with_store_pickup | 2160 | woocommerce_after_checkout_validation | 擋 LINE Pay + 超商組合 |
newebpay_handle_non_cvscom_shipping | 2181 | woocommerce_checkout_posted_data | 非超商時清掉 CVSCOM 欄位 |
newebpay_intercept_before_payment_page | 2221 | woocommerce_receipt_newebpay(priority 0) | 補正訂單 meta,最後攔截點 |
newebpay_filter_cvscom_settings | 2278 | option_woocommerce_newebpay_settings | 動態關閉外掛超商付款設定 |
newebpay_modify_auto_submit_time | 2381 | wp_footer(order-pay) | 自動跳轉 10s → 3s |
newebpay_cvscom_fix_status | 173 | woocommerce_order_status_changed(priority 999) | 狀態回退:選店後保持 pending |
newebpay_cvscom_manual_update | 238 | woocommerce_payment_complete | 後台手動「更新交易狀態」時補正 |
5.2 LINE Pay 流程與限制
- 外掛:
woocommerce-gateway-linepay - 限制:LINE Pay 不支援超商取貨,前端 + 後端雙重擋(模組 U + V)。
- 狀態異常自動修復(模組 N):
訂單由 processing → failed ↓ log_status() 排程一次性 cron(5 分鐘後) ↓ check_linepay_success_handler() ├─ 讀取 _linepay_payment_status ├─ 若 = 'confirmed',改回 processing └─ 寄信通知 4 位管理員(hello/joanna/Ruby/DD@chunling.com.tw)
5.3 排錯入口
| 症狀 | 檢查點 |
|---|---|
| 超商取貨訂單一下單就變 completed | newebpay_cvscom_fix_status 是否被掛上 priority 999 |
| 訂單備註有「店家:」但沒「付款時間」 | 屬於正常(顧客已選店、未取貨),狀態應為 pending |
| 結帳頁出現「LINE Pay 不支援超商」 | 預期行為,模組 V 後端阻擋 |
| 藍新導頁顯示「無此付款方式」 | 模組 X newebpay_filter_cvscom_settings 是否錯誤關閉設定 |
| 後台儲存藍新外掛設定無效 | 模組 X 的 if (is_admin()) 早退是否被破壞 |
| 結帳沒選運送方式就顯示超商付款選項 | 模組 U isStorePickingShipping() 的「只有一個運送方式」邏輯 |
6. 開發守則
6.1 絕對不可違反
- 絕不直接編輯父主題
woodmart/——升級會洗掉所有改動。 - 絕不直接編輯外掛資料夾——所有客製透過 hook 在 child theme 完成。
- 絕不在
wp-config.php之外硬編 API Key——使用define('OPENAI_API_KEY', ...)。 - AJAX handler 必須
check_ajax_referer()(防 CSRF)。 - 所有
$_GET/$_POST必須 sanitize(absint、sanitize_text_field等)。 - 修改
functions.php後必跑php -l語法檢查:bashphp -l wp-content/themes/woodmart-child/functions.php - 修改
main.js後必同步main.min.js(見第 3 章)。
6.2 Hook 優先級慣例
| 優先級 | 用途 | 例子 |
|---|---|---|
| 0 | 最早攔截 | newebpay_intercept_before_payment_page |
| 5 | 早期過濾 POST 資料 | newebpay_handle_non_cvscom_shipping |
| 10 | WordPress 預設 | 大多數 hook |
| 15 | 資產 URL 過濾 | crave_script_version_with_filemtime |
| 100 | 運費過濾 | my_hide_shipping_when_free_is_available |
| 999 | 訂單狀態強制修正 | newebpay_cvscom_fix_status |
| 1000 | 子主題資產載入 | woodmart_child_enqueue_styles |
| 9999 | 最晚攔截外掛設定 | newebpay_filter_cvscom_settings |
6.3 Cron 任務管理
- 自訂排程頻率寫在
add_quarterly_cron_schedule()(line 1460) - 排程任務必須在
register_deactivation_hook()中清除,避免主題停用後成為孤兒 - 使用 [WP-Crontrol] 外掛可在後台檢視所有 cron 任務
6.4 偵錯模式
php
// wp-config.php
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);bash
tail -f wp-content/debug.logfunctions.php 中已有大量 error_log() 與 console.log()(特別在藍新整合區),上線前可考慮關閉但不要刪除(出問題時是救命用)。
7. 常見開發任務指南
7.1 新增 WooCommerce 客製 Hook
php
add_action('woocommerce_xxx_hook', 'my_callback', 10, $arg_count);
function my_callback($args) {
// 1. 確認觸發條件(運送/付款/狀態)
// 2. 操作前先讀取現有 meta 避免覆蓋
// 3. 結束時 $order->save()
}測試清單:
- [ ] 用宅配 + 信用卡測試
- [ ] 用 6H 配送 + 信用卡測試
- [ ] 用超商取貨付款測試
- [ ] 用超商取貨不付款測試
- [ ] 用 LINE Pay 測試(注意不可選超商)
- [ ] 國際地址結帳測試
7.2 修改結帳欄位
- 在
set_checkout_field_default_value()加入新欄位的預設值(line 1364) - 在
wps_select_checkout_field_process()加入後端驗證(line 671) - 在
custom_checkout_field_script()加入前端條件顯示(line 515) - 用
update_user_gender_meta()模式儲存到 user meta(line 1346)
7.3 新增 shortcode(含 AJAX)
參考 gpt_question_button_shortcode(line 1485)+ gpt_handle_ajax_request(line 1520)模式:
add_shortcode()註冊wp_enqueue_script+wp_localize_script傳 noncewp_ajax_xxx+wp_ajax_nopriv_xxx雙註冊- handler 內
check_ajax_referer() - 回應用
wp_send_json_success/wp_send_json_error
7.4 Template Override
bash
# 從父主題或外掛複製到子主題(保留路徑)
cp wp-content/themes/woodmart/woocommerce/checkout/form-checkout.php \
wp-content/themes/woodmart-child/woocommerce/checkout/form-checkout.php⚠️ Template override 是雙刃劍:父主題/WooCommerce 升級時可能不相容,需定期回頭比對。
8. 第三方整合與外掛清單
金流
| 外掛 | 用途 |
|---|---|
newebpay-payment | 藍新金流主要外掛(含超商取貨) |
newebpay(舊版) | 已被 newebpay-payment 取代,但部分 meta key 沿用 |
woocommerce-gateway-linepay | LINE Pay |
追蹤
- Google Tag Manager(GTM-PC8K325)
- Google Analytics 4(G-Z5C8WK0J0F)
- Facebook Pixel + PixelYourSite Pro
- LINE Tag(tagId:
7873c94a-88a8-4847-a533-5fff1f881a8b) - AddToAny(含自訂 LINE 加好友)
- VBTrax 聯盟追蹤(shortcode
[affiliates])
安全
- iThemes Security(Better WP Security)
- Security Ninja Premium
- Two-Factor Authentication
- Advanced noCAPTCHA & reCAPTCHA
SEO / 內容
- Yoast SEO(含英文版 noindex 規則)
- Breadcrumb NavXT(
bcn_display()) - Advanced Order Export For WooCommerce(已開放自訂 PHP)
會員 / 多語
- Ultimate Member(會員系統)
- WPML(多語,若啟用)
維護
- All-in-One WP Migration(備份/搬遷)
- WP-Crontrol(cron 管理)
- Health Check & Troubleshooting(mu-plugin)
9. 效能與快取
| 機制 | 說明 |
|---|---|
object-cache.php | Redis/Memcached 物件快取(wp-content/object-cache.php) |
| W3 Total Cache | 頁面/瀏覽器/資料庫快取 |
| 資產 filemtime 版控 | crave_script_version_with_filemtime()(line 17)替換所有主題 CSS/JS 的 ?ver=,瀏覽器自動破快取 |
wp_gpt_answers 表 | GPT 回應快取(避免重複呼叫 OpenAI) |
woodmart_exclude_cat_* transient | 排除分類的商品 ID 快取 1 小時(line 1646) |
10. 附錄:關鍵函式速查表
資產 / 前端最佳化
| 函式 | 行號 | 用途 |
|---|---|---|
woodmart_child_enqueue_styles | 5 | 載入子主題 CSS/JS |
crave_script_version_with_filemtime | 17 | 自動版本號 |
add_custum_fontfamily | 47 | TinyMCE 中英文字型 |
crave_disable_emojis | 373 | 移除 emoji 載入 |
crave_disable_embeds | 419 | 移除 oEmbed |
crave_remove_jquery_migrate | 458 | 移除 jQuery Migrate |
dns_prefetch | 466 | 加上 DNS prefetch hints |
訂單 / 運費
| 函式 | 行號 | 用途 |
|---|---|---|
my_hide_shipping_when_free_is_available | 62 | 免運顯示規則 |
wh_CustomReadOrder | 90 | GA4 purchase event |
affiliates_trank | 121 | VBTrax 聯盟追蹤 shortcode |
custom_shop_order_column | 281 | 後台訂單欄位 |
custom_orders_list_column_content | 296 | 「需出貨」標記內容 |
log_status | 1289 | LINE Pay 狀態異常排程 |
check_linepay_success_handler | 1310 | LINE Pay 自動修復 |
ctk_check_order_stay_too_long | 1185 | 取消過久未付款訂單(停用中) |
藍新超商整合(最關鍵)
| 函式 | 行號 | 用途 |
|---|---|---|
newebpay_cvscom_fix_status | 173 | 選店後狀態回退 pending |
newebpay_cvscom_manual_update | 238 | 後台手動更新狀態補正 |
WC_Custom_CVSCOM_Shipping_Method | 1681 | 自訂超商取貨運送方式類別 |
newebpay_shipping_payment_integration | 1816 | 結帳頁 JS 整合 |
prevent_linepay_with_store_pickup | 2160 | 擋 LINE Pay+超商 |
newebpay_handle_non_cvscom_shipping | 2181 | 清非超商的 CVSCOM 資料 |
newebpay_intercept_before_payment_page | 2221 | receipt 頁補正 meta |
newebpay_filter_cvscom_settings | 2278 | 動態關閉外掛設定 |
newebpay_modify_auto_submit_time | 2381 | 自動跳轉 3 秒 |
結帳欄位
| 函式 | 行號 | 用途 |
|---|---|---|
filter_default_address_fields | 498 | 設定地址欄位非必填 |
custom_checkout_field_script | 515 | 動態顯示/隱藏欄位 JS |
wps_select_checkout_field_process | 671 | 後端驗證 |
checkout_action_wp_footer | 731 | 6H 注意事項彈窗 |
update_user_gender_meta | 1346 | 性別存 user meta |
set_checkout_field_default_value | 1364 | 性別欄位預設值 |
學生角色
| 函式 | 行號 | 用途 |
|---|---|---|
add_student_role | 1411 | 註冊 role |
add_student_role_on_coupon_use | 1425 | st- 開頭優惠券觸發 |
check_and_remove_expired_student_roles | 1439 | 季度移除超過 1 年的角色 |
add_quarterly_cron_schedule | 1460 | 季度排程 |
schedule_quarterly_student_role_check | 1470 | 註冊 cron |
deactivate_quarterly_student_role_check | 1478 | 停用主題時清除 cron |
GPT 問答
| 函式 | 行號 | 用途 |
|---|---|---|
gpt_question_button_shortcode | 1485 | shortcode 渲染 |
gpt_enqueue_scripts | 1511 | 載入 JS + nonce |
gpt_handle_ajax_request | 1520 | AJAX handler(OpenAI 呼叫 + 快取) |
其他
| 函式 | 行號 | 用途 |
|---|---|---|
set_line_tag | 773 | LINE Tag 追蹤 |
set_fb_verification_to_meta | 807 | FB 域名驗證 meta |
set_gtm | 829 | GTM 載入 |
woodmart_page_title | 850 | 覆寫父主題頁標題加 breadcrumbs |
addtoany_add_follow_services | 1215 | AddToAny LINE 加好友 |
wc_check_coupon_is_valid | 1240 | 優惠券 email 限制(不分大小寫) |
setNoindexIfEn | 1272 | 英文版 /en_us/ noindex |
wpwc_fix_yoast_seo_robots_txt | 1391 | 修正 Yoast 對 robots.txt 的覆蓋 |
woodmart_exclude_category_from_related_products | 1608 | 相關商品排除 no-show 分類 |
文件維護
- 本文件對應
functions.php的時間點為 2026-04-29(git commitbe138e14) - 行號可能因後續修改而漂移,請以函式名稱為主、行號為輔
- 如做大幅重構,建議同步更新本文件與
functions.php.txt
