Action vs. Filter 大亂鬥?資深工程師帶你拆解 WordPress Hooks 底層邏輯,別再搞混了!
嗨,我是浪花科技的資深工程師 Eric。在 WordPress 的世界裡打滾了這麼多年,我看過無數開發者,從新手到老手,都會在一個核心觀念上卡關,那就是 WordPress 的 Hooks 系統,特別是 add_action 和 add_filter 這對看似兄弟、實則性格迥異的函式。很多人會說:「啊不就都掛鉤子嗎?能動就好啦!」
唉,這就是典型的工程師壞習慣——「能動就好」。這種心態在初期或許能讓你快速解決問題,但長遠來看,混用 Action 和 Filter 不僅會讓你的程式碼難以維護,更可能埋下難以察覺的效能地雷或邏輯錯誤。今天,就讓我這個老骨頭帶你深入底層,徹底搞懂這兩者的差異,讓你從「會用」晉升到「精通」,寫出更優雅、更健壯的 WordPress 程式碼。
WordPress Hooks 到底是什麼?一個生活化的比喻
在我們深入技術細節前,先來個比喻吧。你可以把 WordPress 核心想像成一棟已經蓋好的房子,裡面有完整的電力系統。而 Hooks 就像是牆上預留的「插座」。
- Action Hooks (動作掛鉤):像是「電源開關」。當你按下開關(例如:文章發佈了),它會觸發一個事件,通知所有連接到這個開關的電器(你的函式)開始運作。例如,按下開關後,電燈亮了、音響響了。它們各自完成自己的任務,但不會互相影響,也不會改變「按下開關」這個事件本身。
- Filter Hooks (過濾器掛鉤):則像是「變壓器」或「濾水器」。電流(資料)流過它時,它會對電流進行加工處理(例如:把 220V 降為 110V),然後再把處理過的電流傳遞下去。它接收一個東西,處理完後,再把「處理過的」東西交出去。如果這個濾水器壞了(忘了回傳處理後的水),那下一關就沒水可用了。
有了這個基本概念,我們就來拆解這兩個函式的真正面貌吧。
add_action:WordPress 事件的觸發器——「去做某件事,別回報!」
Action 的核心精神在於「執行」。當 WordPress 運行到某個特定的時間點(例如 wp_head、save_post、init),它會大喊一聲:「嘿!現在是『儲存文章』時間點了,有沒有人要在這個時候做點什麼?」
這時候,所有透過 add_action('save_post', 'your_function_name'); 掛載的函式就會依照順序被觸發執行。這些函式是「獨立」的,它們的目的不是要修改傳入的資料,而是要執行一個「副作用 (Side Effect)」。
所謂的副作用,就是指函式執行後對外部世界產生的影響,例如:
- 發送一封 Email 通知。
- 將資料寫入 Log 檔。
- 呼叫一個外部 API。
- 更新另一個資料庫欄位。
它們的共同點是:完成任務就結束了,不需要「回報」任何東西給 WordPress 核心。
實戰範例:在文章儲存後自動發送 LINE 通知
想像一下,我們希望編輯每次更新文章時,就自動發送一個通知到公司的 LINE 群組。這就是一個典型的「動作」,我們不是要修改文章內容,而是要觸發一個外部行為。
<?php
/**
* 當文章儲存時,觸發 LINE Notify 通知
*
* @param int $post_id 文章 ID
* @param WP_Post $post 文章物件
* @param bool $update 是否為更新文章
*/
function eric_send_line_notification_on_save($post_id, $post, $update) {
// 防止自動儲存或修訂版本觸發
if (wp_is_post_revision($post_id) || wp_is_post_autosave($post_id)) {
return;
}
// 確保是我們想要的文章類型,例如 'post'
if ($post->post_type !== 'post') {
return;
}
// 這裡只是示意,請替換成你自己的 LINE Notify 邏輯
$token = 'YOUR_LINE_NOTIFY_TOKEN';
$message = '文章已更新:' . get_the_title($post_id) . ' 連結:' . get_permalink($post_id);
$args = [
'headers' => [
'Authorization' => 'Bearer ' . $token,
],
'body' => [
'message' => $message,
],
];
wp_remote_post('https://notify-api.line.me/api/notify', $args);
}
// 將我們的函式掛載到 'save_post' 這個 action hook 上
// 優先權設為 10,並接收 3 個參數
add_action('save_post', 'eric_send_line_notification_on_save', 10, 3);
?>
在這個例子中,eric_send_line_notification_on_save 函式執行了 wp_remote_post 來呼叫外部 API,它沒有回傳任何東西,完美詮釋了 Action 的精神。
add_filter:WordPress 資料的加工廠——「把東西給我,我改完再還你!」
Filter 的核心精神在於「修改」與「回傳」。當 WordPress 準備要輸出一筆資料時(例如文章標題、內容、摘要),它會先把這筆資料透過 Filter 傳遞出去,像是在問:「嘿!這是我準備要顯示的文章標題,有沒有人想在最後一刻對它做點什麼手腳?」
所有透過 add_filter('the_title', 'your_function_name'); 掛載的函式會像一條生產線一樣,依序接收這筆資料,對它進行加工,然後「必須」把加工後的結果回傳(return)出去,交給下一個函式處理。如果中間有任何一個環節忘了回傳,那這筆資料在這條生產線上就斷了,最終輸出的結果可能就是空的,甚至導致網站出錯。
`return` 是 Filter 的靈魂!
這點我要特別囉嗦一下,因為這是新手最常犯的錯。在 Filter 函式中,忘記 `return` 就等於謀殺了那筆資料。你的函式接收了一個參數(例如 $title),你對它做了一些處理,最後一定要 return $title;。就算你沒有做任何處理,也要原封不動地把原始資料 return 回去,否則下一個掛在同一個 Filter 上的函式就收不到東西了。
實戰範例:在文章標題前自動加上「獨家報導:」
假設我們想讓所有文章的標題在顯示時,前面都自動加上一個固定的前綴,這就是一個典型的「修改資料」的場景。
<?php
/**
* 過濾文章標題,在前面加上前綴
*
* @param string $title 原始文章標題
* @param int $id 文章 ID
* @return string 修改後的文章標題
*/
function eric_add_prefix_to_title($title, $id) {
// 只在主要查詢的單篇文章頁面中作用,避免影響選單、後台等地方的標題
if (is_singular('post') && in_the_loop() && is_main_query()) {
return '【獨家報導】' . $title;
}
// 對於其他情況,務必原封不動地回傳原始標題!
return $title;
}
// 將我們的函式掛載到 'the_title' 這個 filter hook 上
// 優先權設為 10,並接收 2 個參數
add_filter('the_title', 'eric_add_prefix_to_title', 10, 2);
?>
看到了嗎?這個函式的結尾無論如何都有一個 return。這就是 Filter 的標準作業流程 (SOP),接收、處理、回傳,缺一不可。
Action vs. Filter 終極對決:一張表格讓你秒懂
講了這麼多,我們來做個總整理,讓你一眼看穿兩者的核心差異。
| 比較項目 | add_action (動作) |
add_filter (過濾器) |
|---|---|---|
| 核心目的 | 在特定時間點「執行」一個或多個函式。 | 在資料傳遞過程中「修改」資料。 |
| 回傳值 | 不需要。函式執行完就結束了。 | 必須有。一定要回傳處理後(或未處理)的資料。 |
| 函式參數 | 通常是事件相關的上下文資訊(如 $post_id, $user_id)。 | 第一個參數必定是要被過濾的資料本身(如 $content, $title)。 |
| 應用場景 | 寄送 Email、註冊腳本 (wp_enqueue_scripts)、註冊文章類型 (init)。 |
修改文章內容 (the_content)、改變摘要長度 (excerpt_length)、自訂 Body Class (body_class)。 |
| 常見錯誤 | 嘗試在 Action 中修改資料並期待它生效(並不會)。 | 忘記 return,導致資料消失,網站畫面空白或出錯。 |
工程師的囉嗦時間:如何找到可用的 Hooks?
好的,現在你懂了 Action 和 Filter 的差別,下一個問題就是:「我怎麼知道 WordPress 在哪些地方安插了這些『插座』?」
- 官方文件是你的聖經:WordPress 開發者中心的 Hooks 列表 是你最好的朋友。雖然是英文,但裡面詳細列出了所有 Action 和 Filter,以及它們的作用和參數。
- 善用偵錯外掛:像是 Query Monitor 這種神器,可以在頁面載入時告訴你當前頁面觸發了哪些 Hooks,以及有哪些函式掛載在上面。這對於理解主題或外掛的運作流程非常有幫助。
- 直接看原始碼:這是最硬核但也是最根本的方法。直接在 WordPress 核心檔案中搜尋
do_action(和apply_filters(,你就能找到所有可用的掛鉤點。這也是我最推薦的方式,因為它能讓你真正理解 WordPress 的底層運作邏輯。
總結:掌握 Hooks,解鎖 WordPress 的無限可能
總結一下今天的重點:
- Action 是「執行者」:在特定時間點做事,不求回報。
- Filter 是「加工者」:接收資料、修改它,然後務必交還回去。
搞懂這兩者的分野,是從 WordPress 小白邁向專業開發者的關鍵一步。它能讓你用最乾淨、最有效率、最符合 WordPress 精神的方式去客製化網站,而不是到處亂改核心檔案或外掛程式碼,造成日後更新的災難。
希望這次的深度拆解對你有幫助。別再把 Action 和 Filter 搞混了,現在就打開你的 functions.php,開始用正確的方式來施展你的 WordPress 黑魔法吧!
延伸閱讀
- 解鎖 WordPress 的任督二脈:搞懂 Action & Filter Hooks,你的客製化功力瞬間爆發!
- 想寫自己的 WordPress 外掛?別再只會複製貼上!資深工程師帶你從零打造第一個外掛
- 解鎖 WordPress 的隱藏力量:functions.php 終極實戰指南,讓你的網站秒變客製化神器!
需要更深入的 WordPress 客製化開發嗎?
如果你覺得這篇文章對你有幫助,但你在專案中遇到了更複雜、更棘手的問題,無論是效能調校、API 串接,還是高難度的客製化功能開發,都歡迎隨時與我們浪花科技的團隊聊聊。我們專注於提供企業級的 WordPress 解決方案,樂於為你打造穩定、高效且具擴展性的網站系統。
→ 立即填寫表單,與我們的技術顧問免費諮詢
常見問題 (FAQ)
Q1: add_action 和 add_filter 最根本的差別是什麼?
最根本的差別在於「目的」和「回傳值」。add_action 的目的是在特定時間點「執行一個動作」(例如寄信、寫入資料庫),它不需要回傳任何東西。而 add_filter 的目的是「修改一筆資料」(例如文章標題、內容),它「必須」將修改後(或未修改)的資料回傳出去,否則會中斷資料鏈,導致錯誤。
Q2: 我在 add_filter 的函式中忘了加 return 會發生什麼事?
這是一個嚴重的錯誤。如果你的 filter 函式沒有回傳值,PHP 會預設回傳 NULL。這意味著傳遞到下一個 filter 或最終要輸出的資料會變成空的。在前端,你可能會看到文章標題或內容消失;在後端,這可能導致功能異常甚至網站出現「死亡白畫面」(White Screen of Death)。
Q3: 我怎麼知道一個外掛或主題用了哪些 hooks?
有幾種方法:第一是查閱該外掛或主題的官方文件。第二是使用像 Query Monitor 這類的開發者工具,它能列出當前頁面所有執行的 hooks。第三,也是最直接的方法,就是閱讀它的原始碼,搜尋關鍵字 do_action 和 apply_filters,就能找到所有它提供給開發者客製化的掛鉤點。






