Action 還是 Filter?WordPress Hooks 二選一難題,走出選擇困難!
☰ 目錄 table-of-contents.md
Action 還是 Filter?關鍵就看你需不需要回傳值
如果你的目的是「改變一段在 WordPress 流程中傳遞的資料」(例如文章標題、查詢參數、產品價格),就用 Filter;如果你的目的是「在某個時間點執行一個動作」(例如輸出追蹤碼、寄信、寫入資料庫),而不需要把結果交回流程,就用 Action。
判斷關鍵只有一個:你需不需要 return 一個值回去?需要回傳 → Filter;不需要回傳 → Action。本文會把這個原則拆解成可實作的決策流程、程式碼範例與常見地雷,讓你以後遇到 add_action 與 add_filter 不再猶豫。
寫程式這麼多年,我看過無數剛踏入 WordPress 開發世界的新手(甚至是老手),在一個看似簡單卻至關重要的十字路口上徘徊不定:我現在這個功能,到底該用 add_action 還是 add_filter?
很多人都聽過最簡單的解釋:「Action 是『做事』,Filter 是『改東西』」。這句話沒錯,但太簡化了。現實世界的開發場景遠比這複雜,魔鬼都藏在細節裡。選錯了,輕則功能不如預期,重則網站效能低落、甚至出現難以追蹤的 Bug。今天就讓我帶你深入 WordPress Hooks 的核心,徹底搞懂兩者的差異與應用。
什麼是鉤子 (Hooks)?WordPress 的彈性靈魂
在深入 Action 和 Filter 的對決之前,得先聊聊「鉤子 (Hooks)」這個概念。身為工程師,我得說 Hooks 絕對是 WordPress 架構中最天才的設計之一:它讓我們可以在不修改核心程式碼的前提下,對 WordPress 的功能進行擴充與客製化。
你可以把整個 WordPress 的執行流程想像成一條高速運轉的生產線。這條生產線在各個關鍵節點——比如「準備顯示文章標題前」、「使用者成功登入後」、「準備載入頁尾腳本時」——都預先埋設了很多「插座」。這些插座就是所謂的「鉤子」。
- Action Hooks:就像生產線上的「警報器插座」。當流程走到這個節點,它會大喊一聲:「現在要執行某某動作了!」任何接上這個插座的函式都會被觸發執行。例如在頁尾
wp_footer這個節點,你可以掛載一個函式來插入追蹤碼。 - Filter Hooks:更像生產線上的「品質檢驗站」。當一個零件(資料)流經這個站點時,它會被攔下來交給你掛載的函式進行「加工」。你可以檢查它、修改它、甚至替換它,但最重要的是,加工完畢後你「必須」把零件放回生產線,讓流程繼續。例如你可以攔截文章標題
the_title,在它前面加上字樣。
理解了這個核心思想,你就會明白為什麼我們總是強調「千萬不要去改 WordPress 核心檔案」。透過 Hooks,我們能用更優雅、更安全、也更具可維護性的方式完成任務。
Action vs. Filter:一張表看懂核心差異
理論講完,先用一張對照表把兩者的本質差異攤開來,後面再進實戰。
| 比較項目 | Action Hook | Filter Hook |
|---|---|---|
| 核心精神 | Fire and Forget(觸發後不理) | Take, Modify, Return(接收、修改、回傳) |
| 主要目的 | 在特定時間點執行一段程式碼 | 過濾並修改一段傳遞中的資料 |
| 是否需要回傳值 | 不需要 | 必須 return |
| 掛載函式 | add_action() | add_filter() |
| 建立鉤子 | do_action() | apply_filters() |
| 典型場景 | 輸出 HTML、寄信、呼叫外部 API、清快取 | 改標題、改內文、改查詢參數、改價格 |
Action Hooks:在特定時間點「執行」一段程式碼
Action 的核心精神是「Fire and Forget」(觸發後不理)。它在特定的時間點被觸發,執行你指定的函式,然後就沒它的事了。它不關心你的函式做了什麼,也不期望你回傳任何東西。
常見使用場景:
- 在頁首或頁尾插入追蹤碼、CSS 或 JavaScript。
- 當一篇文章發佈時,自動發送通知 Email 給作者。
- 當使用者註冊成功後,將他的資料同步到外部的 CRM 系統。
- 清除特定快取。
範例:在網站頁尾加入自訂 JavaScript
假設我們想在每個頁面的 </body> 標籤前加入一段自訂 JavaScript,最適合的 Action Hook 就是 wp_footer。
<?php
// 將這段程式碼加入你的主題 functions.php 或自訂外掛中
function roamer_add_custom_footer_script() {
echo '<script>console.log("Hello from Roamer Tech!");</script>';
}
add_action('wp_footer', 'roamer_add_custom_footer_script');
?>
roamer_add_custom_footer_script 這個函式只是單純地 echo 出一段 script,它沒有回傳任何值。這就是一個標準的 Action 應用。
Filter Hooks:「過濾」並「回傳」修改後的資料
Filter 的核心則是「Take, Modify, Return」(接收、修改、回傳)。它會接收一個或多個參數(通常第一個參數是要被過濾的資料),讓你的函式進行處理,然後它「必須」接收你回傳的值,並用這個新值取代舊值,繼續接下來的流程。
工程師的小囉嗦:我必須再強調一次,Filter 的函式一定要有
return!這是我看過新手最常犯的錯誤之一。如果你忘記return,傳進來的值就會變成NULL,通常會導致網站內容消失或直接白畫面。除錯時,請務必先檢查你的 Filter 函式最後有沒有乖乖return。
常見使用場景:
- 修改文章標題、內文或摘要的顯示方式。
- 變更 WooCommerce 產品的價格。
- 自訂「閱讀更多」的連結文字。
- 在使用者個人資料頁面新增或移除欄位。
範例:將所有文章標題都加上前綴
假設我們希望網站上所有文章的標題前面,都自動加上「[精選文章] 」的字樣,這時候 the_title 這個 Filter Hook 就是你的好朋友。
<?php
// 將這段程式碼加入你的主題 functions.php 或自訂外掛中
function roamer_add_title_prefix($title, $id = null) {
// 只在主循環的單篇文章中修改,避免影響選單、小工具等地方的標題
if (is_singular() && in_the_loop() && is_main_query()) {
return '[精選文章] ' . $title;
}
// 如果不符合條件,務必回傳原始的標題!
return $title;
}
add_filter('the_title', 'roamer_add_title_prefix', 10, 2);
?>
在這個範例中,我們的函式接收了 $title,經過條件判斷後回傳了加工後的新標題,或在不符條件時回傳原始標題。這就是 Filter 的標準作業流程。
那兩個數字是什麼?讀懂優先順序與參數數量
你應該注意到上面的 add_filter('the_title', 'roamer_add_title_prefix', 10, 2) 後面多了 10 跟 2。這是 add_action() 與 add_filter() 都共用的兩個重要參數,搞懂它們能幫你避開很多「為什麼我的函式沒效果」的坑:
- 優先順序 (priority,預設 10):同一個鉤子上可能掛了很多函式。數字越小越早執行、數字越大越晚執行。當你發現自己的修改被別的外掛蓋掉,常見的解法就是把優先順序調大(例如
20、99),讓你的函式在它們之後才跑。 - 接收參數數量 (accepted args,預設 1):這個數字決定 WordPress 會把幾個參數傳進你的函式。以上面的例子來說,
the_title可以提供$title和$id兩個參數,所以我們寫2,函式才拿得到$id。如果你只寫預設的1,第二個參數就會是空的。
我到底該用 Action 還是 Filter?一個決策流程
現在你已了解兩者的運作原理,讓我們建立一個簡單的決策流程,幫助你在開發時快速做出正確選擇。當你有一個需求時,先問自己第一個問題:
「我的主要目的,是要『改變』WordPress 執行流程中傳遞的某個特定資料(字串、陣列、物件等)嗎?」
- 是:恭喜你,99% 的情況下你應該使用 Filter。例如改變文章內容、修改圖片 class、調整查詢參數等。
- 否:接著問第二個問題——「我的主要目的是在某個時間點『觸發』一個獨立的動作(例如寫入資料庫、呼叫外部 API、輸出 HTML),而不需要把結果交還給當前的流程嗎?」
- 是:那毫無疑問,你應該使用 Action。
- 否:那可能需要重新思考你的需求邏輯了。是不是把一個複雜的功能混在一起了?試著把它拆解成更小的步驟,再用這個流程判斷一次。
一個常見的反模式:用 Filter 做 Action 的事
這裡有一個我常看到的反模式:用 Filter 來做 Action 該做的事情。例如有人可能會這樣寫:
<?php
// 錯誤示範!不要這樣做!
add_filter('the_title', function($title) {
// 在 filter 裡面做與資料修改無關的事情
error_log('這篇文章被瀏覽了:' . $title);
return $title;
});
?>
雖然這段程式碼能跑,但這是非常糟糕的設計。the_title 這個 filter 在一個頁面載入的過程中可能會被呼叫數十次(標題、瀏覽器頁籤、導覽麵包屑……),你的 error_log 就會被瘋狂觸發,造成不必要的效能浪費和混亂的日誌。正確的做法應該是找一個更適合、且只執行一次的 Action(例如 wp_head 或 loop_start)來執行這個紀錄行為。
進階應用:打造可擴充的程式碼
當你掌握了 Action 和 Filter,下一步就是學會建立自己的 Hooks,讓你的外掛或主題也擁有像 WordPress 核心一樣的擴充能力。
do_action('my_custom_action', $arg1, $arg2);:在你的程式碼中建立一個 Action 鉤子,純粹通知「這件事發生了」。apply_filters('my_custom_filter', $data_to_filter, $arg1);:建立一個 Filter 鉤子,把$data_to_filter交給外部加工後,用回傳值繼續流程。
當你開發一個複雜的外掛時,在關鍵流程中埋設自己的 Hooks,可以讓其他開發者(甚至是未來的你)更容易擴充與客製化功能,而不需要去修改外掛原始碼。這是一個專業 WordPress 開發者必備的思維。如果你想更系統地練習「自己造 Hook」,可以延伸閱讀我們從自訂 Action/Filter 到打造可擴展外掛架構的實戰文章。
總結
Action 和 Filter 是 WordPress 開發的基石。記住那個最關鍵的判準:需要回傳值就用 Filter,不需要回傳值就用 Action。別再只是模糊地用「做事」和「改東西」來區分,深入理解它們的運作哲學,並在對的場景使用對的工具,你就能寫出乾淨、高效、可維護的程式碼。
希望這篇文章能幫你解開長久以來的疑惑。如果你在 WordPress 開發上遇到了更複雜的架構問題,或是需要打造高度客製化的企業級網站,浪花科技的團隊擁有豐富的實戰經驗。
歡迎點擊這裡,填寫表單與我們聯繫,讓我們用專業的技術,為您的事業打造穩固的數位基礎!
延伸閱讀
常見問題
WordPress 開發該用 Action 還是 Filter?怎麼快速判斷?
Action Hook 和 Filter Hook 的核心差異是什麼?
為什麼 Filter 函式忘記 return 會讓網站出問題?
add_filter 後面的兩個數字 10 和 2 是什麼意思?
訂閱免費電子報
把 AI 自動化、企業系統設計與 WordPress / Laravel 開發的真實案例和可直接照做的技巧,整理成電子報寄給你。只寄精選內容、不灌垃圾信,一鍵就能退訂。