Action 和 Filter 你真的懂了嗎?資深工程師揭秘 WordPress Hooks 的『架構思維』,不只是執行與修改!
Hey,我是浪花科技的資深工程師 Eric。寫了這麼多年的 WordPress,我看過無數的 `functions.php`,從新手寫的複製貼上大雜燴,到高手寫的優雅模組化程式碼。而這其中最大的分水嶺,往往就在於對 WordPress 核心機制——Hooks——的理解深度。
我知道,你可能已經在某個教學文章看過:「Action 是用來『做』事情的,Filter 是用來『改』東西的。」這句話沒錯,但這只是幼幼班等級的理解。就像你知道汽車有油門跟煞車,不代表你就是個賽車手。真正的關鍵在於,你是否理解在何種情境下、基於何種「架構思維」來選擇使用 Action 還是 Filter?這才是決定你的程式碼是個可靠的建築,還是一棟搖搖欲墜的違章建築的根本。今天,我們不只談差異,更要談背後的設計哲學。
WordPress Hooks 核心:事件驅動的交響樂
在我們深入 Action 與 Filter 的戰場之前,先花點時間校準一下觀念。WordPress Hooks 本質上是一套「事件驅動」或「發布/訂閱」的設計模式。你可以把它想像成一場盛大的交響樂演奏會。
WordPress 核心程式碼就是那位總指揮,它會在特定的時間點(例如:`’init’` 系統初始化時、`’publish_post’` 文章發布時、`’wp_head’` 輸出 `
` 內容時)大喊一聲:「現在,輪到這個樂章了!」這個「大喊」的動作,就是觸發一個 Hook。- Action Hooks:總指揮喊:「第一小提琴部,現在請演奏你們的段落!」然後小提琴部就開始演奏。他們不需要把樂譜交還給指揮,他們只是在那個時間點「執行」了他們的任務。
- Filter Hooks:總指揮把一份基礎樂譜傳下去,說:「弦樂部,請根據這份樂譜即興發揮,然後把修改後的版本傳給下一部。」弦樂部拿到樂譜、修改、然後再傳下去。每一部都必須「回傳」一份樂譜,哪怕沒有修改,也要把原版的傳下去,不然演奏會就中斷了。
所以,理解 WordPress Hook 與 Filter 差異與應用 的第一步,就是明白它們都是這場交響樂的一部分,只是扮演的角色與職責截然不同。
Action Hooks:使命必達的『執行者』
Action Hook 的核心精神是「副作用 (Side Effect)」。聽起來有點嚇人,但在程式設計裡,這只是指一個函式除了回傳值之外,還對外部狀態產生了影響。例如:寫入資料庫、發送 email、呼叫 API、清除快取…這些都是副作用。
實戰情境:當文章發布時,自動通知 Slack
這是一個典型的 Action 應用。我們希望在 `publish_post` 這個事件發生時,執行一個「發送通知到 Slack」的動作。這個動作不需要回傳任何東西給 WordPress 核心,它只要默默完成任務就好。
<?php
/**
* 當有新文章發布時,發送通知到 Slack
*
* @param int $post_ID 文章 ID.
* @param WP_Post $post 文章物件.
*/
function notify_slack_on_publish( $post_ID, $post ) {
// 確保這是一個 'post' 類型的文章,而不是頁面或自訂文章類型
if ( $post->post_type !== 'post' ) {
return;
}
// 這裡只是個範例,實際上你需要處理文章狀態,避免重複發送
if ( wp_is_post_revision( $post_ID ) ) {
return;
}
$slack_webhook_url = 'https://hooks.slack.com/services/YOUR/WEBHOOK/URL';
$post_title = $post->post_title;
$post_url = get_permalink( $post_ID );
$message = sprintf("新文章發布啦!快來看:%s - %s", $post_title, $post_url);
$payload = json_encode(['text' => $message]);
// 使用 WordPress 的 HTTP API 發送請求
wp_remote_post($slack_webhook_url, [
'body' => $payload,
'headers' => ['Content-Type' => 'application/json'],
]);
}
// 將我們的函式「掛」到 'publish_post' 這個 Action Hook 上
// 數字 10 是優先級,2 是指我們的函式接受 2 個參數
add_action( 'publish_post', 'notify_slack_on_publish', 10, 2 );
?>
工程師的小囉嗦: Action 的 callback 函式雖然不用 `return`,但千萬別忘了做錯誤處理和條件判斷。像上面範例中的 `if ( $post->post_type !== ‘post’ )` 就是一個很好的習慣。否則,你可能會發現連更新一個「頁面」都會觸發 Slack 通知,那可就糗大了。
Filter Hooks:巧奪天工的『改造者』
Filter Hook 的核心精神是「資料轉換 (Data Transformation)」。它的使命很單純:接收一個值,對它進行修改,然後把它回傳,讓 WordPress 核心繼續接下來的流程。如果你忘了回傳,那就像交響樂的樂譜在你手上弄丟了,後面的樂手都不知道該演奏什麼,網站很可能就直接白畫面給你看。
實戰情境:為特定會員等級的商品價格打折
假設我們經營一個 WooCommerce 網站,希望「VIP 會員」在瀏覽商品時,能看到 8 折的專屬價格。這就是一個完美的 Filter 應用場景。我們需要攔截(Hook)原始價格,判斷當前使用者身份,然後回傳一個修改後的新價格。
<?php
/**
* 為 VIP 會員提供商品價格折扣
*
* @param float $price 原始價格.
* @param WC_Product $product 商品物件.
* @return float 修改後的價格.
*/
function apply_vip_discount_to_price( $price, $product ) {
// 檢查使用者是否登入
if ( ! is_user_logged_in() ) {
return $price; // 沒登入,回傳原價
}
$user = wp_get_current_user();
$vip_role = 'vip_customer'; // 假設你的 VIP 會員角色 slug 是這個
// 檢查使用者是否擁有 VIP 角色
if ( in_array( $vip_role, (array) $user->roles ) ) {
// VIP 會員打 8 折
$discount_price = $price * 0.8;
return $discount_price;
}
// 如果不是 VIP,就回傳原始價格
return $price;
}
// 將我們的函式「掛」到 WooCommerce 的 'woocommerce_product_get_price' 這個 Filter Hook 上
add_filter( 'woocommerce_product_get_price', 'apply_vip_discount_to_price', 10, 2 );
add_filter( 'woocommerce_product_get_regular_price', 'apply_vip_discount_to_price', 10, 2 );
?>
工程師的小囉嗦: 看到上面程式碼最後的 `return $price;` 了嗎?這是 Filter 的保命符!你的函式中可能有很多條件分支,但你必須保證在任何情況下,都有一個 `return` 陳述句。忘記這個,你的客戶可能會打電話來抱怨為什麼所有非 VIP 會員看到的價格都是 $0。
架構思維:何時用 Action?何時用 Filter?
現在,我們來談談最重要的部分——架構思維。當你面對一個需求時,該如何判斷要用哪個 Hook?
關鍵決策點:意圖與回傳值
- 你的意圖是什麼? 是要「觸發一個獨立的動作」,還是要「改變一個既有的數值」?
→ 如果是前者(例如:使用者註冊後,寄送歡迎信),請用 Action。
→ 如果是後者(例如:改變文章標題前的「私密:」文字),請用 Filter。 - 你需要回傳一個值給 WordPress 嗎? 這個流程需要你把修改後的結果交回去嗎?
→ 如果不需要,只是單向的執行命令,請用 Action。
→ 如果需要,而且後續的程式碼會依賴你回傳的值,那非 Filter 莫屬。
一個容易混淆的例子:修改文章內容
假設需求是:「在每篇文章內容的結尾,自動加上版權宣告。」
新手可能會想:「我要『加上』東西,這是一個『動作』,應該用 Action 吧?」——這就是典型的思維誤區。
正確的思路應該是:
- 我要處理的對象是「文章內容 (`the_content`)」。
- 我不是要觸發一個獨立的外部動作,而是要「修改」這個內容本身。
- WordPress 在顯示文章內容時,會把內容資料 (`$content`) 傳出來,並期望收到一個修改後的版本再顯示到畫面上。
結論:這顯然是一個資料轉換的過程,所以我們應該使用 `the_content` 這個 Filter。
<?php
function add_copyright_to_content( $content ) {
// 只在單篇文章頁面,且在主循環中生效
if ( is_single() && in_the_loop() && is_main_query() ) {
$copyright_text = '<p><em>本文版權所有,轉載請註明出處。</em></p>';
return $content . $copyright_text;
}
return $content;
}
add_filter( 'the_content', 'add_copyright_to_content' );
?>
結論:從「會用」到「精通」
掌握 WordPress Hook 與 Filter 差異與應用,不只是記住 `add_action` 和 `add_filter` 的語法。它代表著你開始用 WordPress 的「語言」去思考問題,去設計你的程式碼架構。
Action 像是程式流程中的宣告與命令,它讓你在特定時刻介入並執行任務;Filter 則是流程中的對話與協商,它讓你有機會修改資料,影響最終的結果。當你能夠憑直覺判斷一個需求應該用 Action 的「命令模式」還是 Filter 的「協商模式」來解決時,你就真正從一個 WordPress 的使用者,晉升為一個 WordPress 開發者了。
希望這篇文章能幫助你建立更深層次的 Hooks 架構思維。如果你還有更複雜的客製化需求,或是企業級的網站架構問題,別忘了,浪花科技的團隊永遠在這裡。
推薦閱讀
- 解鎖 WordPress 的隱藏力量:functions.php 終極實戰指南,讓你的網站秒變客製化神器!
- 不只會用,更要會『造』!WordPress Hooks 終極實戰:從自訂 Action/Filter 到打造可擴展外掛架構
- 改壞主題就回不去了?資深工程師手把手教你用「子佈景主題」安全客製化 WordPress!
對於 WordPress 的客製化開發、效能調校,或是需要打造穩固的企業級網站架構嗎?我們的團隊擁有豐富的實戰經驗,能夠為您提供最專業的解決方案。歡迎點擊這裡,填寫表單與我們聯繫,讓浪花科技成為您最強大的技術後盾!
常見問題 (FAQ)
Q1: Action 和 Filter 最直觀的差別是什麼?
最核心的差別在於「回傳值」。Action Hook 的函式是去「執行一個動作」,例如發送郵件、更新資料庫,它不需要回傳任何東西給 WordPress。而 Filter Hook 的函式是去「修改一個資料」,例如改變文章標題、調整商品價格,它「必須」回傳一個值(修改後的或原始的),否則會中斷程式流程,可能導致網站出錯。
Q2: 我可以在 Filter 裡面執行 Action 嗎?(例如在修改價格的同時,順便寄一封信)
技術上是可行的,但從軟體架構的角度來說,這是一個非常不好的習慣。Filter 的設計初衷是「純粹的資料轉換」,不應該產生「副作用」(Side Effect),如寄信或寫入資料庫。把這些動作混在 Filter 裡,會讓程式碼變得難以預測、難以除錯,也違反了單一職責原則。比較好的做法是,找到一個合適的 Action Hook 來執行寄信這類動作。
Q3: 我怎麼知道 WordPress 核心或外掛提供了哪些可以用的 Hooks?
有幾個好方法:第一,查閱官方文件,WordPress 有一個 Hook Reference 網站,可以查詢核心的 Hooks。第二,直接閱讀原始碼。這聽起來很硬核,但卻是最直接的方式。在 WordPress 核心或外掛的程式碼中搜尋關鍵字 `do_action` 和 `apply_filters`,你就能找到所有可用的掛載點。許多高品質的外掛(如 WooCommerce)也都有非常詳盡的開發者文件會列出它們提供的 Hooks。






