Action 和 Filter 還在傻傻分不清楚?秒懂 WordPress Hooks 的任督二脈!
☰ 目錄 table-of-contents.md
說穿了,Hook 就是 WordPress 在執行流程的特定時間點留給你的插入口,讓你把自己的程式碼掛進去。Action 與 Filter 的差別也很單純:前者負責「做事」,後者則是「改完值再交回去」。觀念看似簡單,但分不清這兩者,正是許多人在 functions.php 裡複製貼上、一出錯就懷疑人生的根源。
今天,我得來跟你囉嗦一下 WordPress 開發的基石,也是區分「外掛安裝工」與「真正開發者」的關鍵分水嶺——那就是 WordPress Hooks。特別是裡面最常讓人搞混的兩兄弟:`Action Hook` 和 `Filter Hook`。搞懂它們的差異與應用,你的 WordPress 開發功力絕對能瞬間打通任督二脈,從此海闊天空。
WordPress Hooks 的核心精神:一切皆是「事件驅動」
在我們深入探討 Action 和 Filter 的差異之前,你必須先理解 WordPress 的運作哲學。你可以把 WordPress 想像成一條精密的工廠生產線,從接收請求到最終輸出一個完整的網頁,中間會經過數百個固定的「工作站」。
例如:
- 「準備初始化」工作站 (`init`)
- 「準備輸出網頁頭部」工作站 (`wp_head`)
- 「準備儲存一篇文章」工作站 (`save_post`)
- 「準備顯示文章內容」工作站 (`the_content`)
這些「工作站」就是所謂的 Hook(掛鉤)。WordPress 核心團隊非常聰明地在這些關鍵節點放了鉤子,讓我們開發者可以在不修改核心程式碼的前提下,把自己寫的功能「掛」上去。這就是所謂的「事件驅動(Event-Driven)」架構,也是 WordPress 能擁有如此龐大生態系的核心秘密。而 `Action` 和 `Filter` 就是我們用來掛上功能的兩種主要工具。
`add_action`:在特定時間點「執行」任務的命令官
先來說說 `Action Hook`。你可以把它想像成一個「廣播系統」。當生產線走到某個工作站時,它會對外大喊一聲:「嘿!我現在要載入頁首囉!」或「注意!這篇文章要發佈囉!」。
而我們使用 `add_action()`,就是在跟 WordPress 說:「聽到那個『發佈文章』的廣播時,麻煩幫我執行一下我指定的這段程式碼。」
`add_action` 是什麼?
簡單來說,`Action` 的核心精神是「執行(Do)」。它在特定的時間點觸發一個或多個函式,用來完成某項任務,例如:
- 載入 CSS 或 JavaScript 檔案。
- 在文章儲存後,發送一封 Email 通知。
- 當使用者登入時,在資料庫裡記錄一筆 Log。
最重要的一點:Action 執行完就沒事了,它不關心結果,也不需要回傳任何東西給 WordPress。就像你交代秘書去寄信,你只關心「寄信」這個動作有沒有被執行,而不是要他回報信的內容是什麼。
`add_action` 語法與參數解析
它的基本語法長這樣:
add_action( 'hook_name', 'your_callback_function', $priority, $accepted_args );- `hook_name`:你要掛上的那個鉤子名稱,例如 `wp_enqueue_scripts`。
- `your_callback_function`:聽到廣播後要執行的函式名稱。
- `$priority`:(選填)優先級,數字越小越先執行,預設是 10。
- `$accepted_args`:(選填)你的函式準備接收多少個參數,預設是 1。
實戰範例:在網站前台載入自訂的 CSS 樣式
這大概是每個主題開發者最常用的 Action 了。我們要在 `wp_enqueue_scripts` 這個鉤子上,掛上一個載入 CSS 的函式。
<?php
// 在 functions.php 中加入
function roamer_enqueue_custom_styles() {
// 註冊並載入我們的 CSS 檔案
wp_enqueue_style(
'roamer-custom-style',
get_stylesheet_directory_uri() . '/css/custom.css',
[],
'1.0.0'
);
}
// 將我們的函式掛到 wp_enqueue_scripts 這個 Action Hook 上
add_action( 'wp_enqueue_scripts', 'roamer_enqueue_custom_styles' );
?>你看,`roamer_enqueue_custom_styles` 這個函式只負責執行 `wp_enqueue_style`,它不需要 `return` 任何東西。
`add_filter`:在資料傳遞中「修改」內容的攔截手
如果說 Action 是廣播系統,那 `Filter Hook` 就是「品管員」。當生產線上的某個零件(資料)要傳到下一個工作站前,品管員會把它攔截下來,檢查一下,甚至動手修改一番,然後再把它放行,交給下一個流程。
`add_filter` 是什麼?
`Filter` 的核心精神是「修改(Modify)」。它接收一個值(例如文章標題字串),對它進行處理,然後 **必須** 把處理後的值回傳出去。
應用場景包括:
- 在文章標題前加上「最新消息:」的前綴。
- 修改文章摘要的預設長度。
- 把文章內容中的特定關鍵字自動加上超連結。
這裡畫個大重點,也是新手最常犯的錯:Filter 的函式如果沒有 `return` 一個值,那原本的資料就會變成 `null`(空),你的網站內容可能就直接消失了! 這就像品管員把零件攔下來,結果忘了放回去,生產線就斷了。
`add_filter` 語法與參數解析
語法跟 `add_action` 幾乎一樣:
add_filter( 'hook_name', 'your_callback_function', $priority, $accepted_args );唯一的差別在於,你傳入的 `your_callback_function` 的第一個參數通常就是準備要被修改的資料,而且函式最後一定要 `return` 這個(或修改後的)資料。
實戰範例:修改文章摘要(Excerpt)的預設字數
WordPress 預設的文章摘要長度是 55 個字,如果我們想改成 20 個字,就可以用 `excerpt_length` 這個 Filter Hook。
<?php
// 在 functions.php 中加入
function roamer_custom_excerpt_length( $length ) {
// 把原本的 $length (預設是 55) 改成 20
return 20;
}
// 將我們的函式掛到 excerpt_length 這個 Filter Hook 上
add_filter( 'excerpt_length', 'roamer_custom_excerpt_length', 999 );
?>看到 `return 20;` 了嗎?我們把傳進來的 `$length` 變數直接忽略,強行回傳 20。WordPress 收到這個回傳值後,就會用 20 作為新的摘要長度。
終極對決:`add_action` vs. `add_filter` 一次看懂
說了這麼多,我幫你整理一下,讓你徹底告別混亂:
- 核心目的:
- `add_action`:執行一個動作 (Do something)。
- `add_filter`:修改一個數值 (Modify something)。
- 回傳值:
- `add_action` 的回呼函式不需要 `return`。
- `add_filter` 的回呼函式必須 `return` 一個值,否則會出大事。
- 數據流:
- `add_action` 是單向的,觸發了就結束了,像個開關。
- `add_filter` 是雙向的,它會攔截數據流,處理後再放行,像個閥門。
- 問自己一個問題:
- 「我想要在『某個時間點』做一件事嗎?」 -> 用 `Action`。
- 「我想要在『某個資料被使用前』改它的內容嗎?」 -> 用 `Filter`。
進階實戰:當 Action 遇上 Filter 的協奏曲
真正的開發場景中,Action 和 Filter 常常需要攜手合作。讓我們來看一個更真實的例子:
情境: 我們希望在文章儲存時(Action),檢查文章內容。如果內容中包含了「機密」這個關鍵字,我們就在標題前自動加上「[內部文件]」的前綴(Filter)。
這個需求完美地展現了兩者的協同作戰:
- 我們需要監聽「文章儲存」這個事件 -> 使用 `save_post` 這個 `Action Hook`。
- 在事件觸發後,我們需要修改文章的標題 -> 這顯然是 `Filter` 的工作,但 `save_post` 是一個 Action,它不處理標題。怎麼辦?我們可以在 `save_post` 觸發的函式裡,動態地去修改文章資料本身。
<?php
// 在 functions.php 中加入
function roamer_check_post_content_on_save( $post_id, $post, $update ) {
// 如果是自動草稿或修訂版本,則不處理
if ( wp_is_post_revision( $post_id ) || wp_is_post_autosave( $post_id ) ) {
return;
}
// 檢查文章內容是否包含 '機密'
if ( strpos( $post->post_content, '機密' ) !== false ) {
// 檢查標題是否已經有前綴,避免重複添加
if ( strpos( $post->post_title, '[內部文件]' ) === false ) {
// 建立要更新的文章資料陣列
$updated_post = array(
'ID' => $post_id,
'post_title' => '[內部文件] ' . $post->post_title,
);
// 因為我們在 save_post 這個 hook 裡,如果直接用 wp_update_post 會造成無限迴圈
// 所以要先移除我們自己的 hook,更新完再加回來
remove_action( 'save_post', 'roamer_check_post_content_on_save', 10, 3 );
wp_update_post( $updated_post );
add_action( 'save_post', 'roamer_check_post_content_on_save', 10, 3 );
}
}
}
// 我們將函式掛在 save_post 這個 Action 上
// 注意!我們需要傳入 3 個參數,所以最後一個數字是 3
add_action( 'save_post', 'roamer_check_post_content_on_save', 10, 3 );
?>這個範例稍微複雜,但完美詮釋了「在一個動作(Action)中,去觸發一個資料的修改(Modification)」的過程。這就是進階開發的日常。
總結:別再害怕,動手去玩吧!
恭喜你!如果你能耐心看到這裡,代表你已經超越了 80% 的 WordPress 使用者。`Action` 和 `Filter` 是 WordPress 賦予開發者最大的自由,也是所有外掛和主題的靈魂所在。
一開始可能會覺得抽象,但最好的學習方式就是「動手做」。試著去修改看看你的文章標題、在頁尾加上一段文字、或是在使用者登出時做點什麼。當你成功掛上第一個 Hook,並看到它如預期般運作時,那種成就感,就是身為一個工程師最大的樂趣。
希望這篇有點囉嗦的文章能幫助你打通對 WordPress Hooks 的理解。不要再把 `functions.php` 當成神秘的黑盒子,把它變成你揮灑創意的畫布吧!
相關閱讀
- Action 和 Filter 你真的懂了嗎?資深工程師揭秘 WordPress Hooks 的『架構思維』,不只是執行與修改!
- functions.php 不是只能複製貼上!資深工程師解鎖 WordPress 主題的『大腦中樞』
- 別再只會 echo ‘Hello World’!資深工程師帶你打造第一個『真正有用』的 WordPress 外掛
如果你在 WordPress 開發上遇到了更複雜的挑戰,或是有企業級的客製化需求,單靠理解 Hooks 可能還不夠。浪花科技專注於打造高效、穩定且可擴展的 WordPress 解決方案。歡迎點擊這裡,填寫表單聯繫我們,讓我們的專業團隊為你的專案賦能!
常見問題
WordPress 的 Action Hook 和 Filter Hook 有什麼差別?
Filter 的回呼函式如果忘了 return 會怎樣?
add_action 與 add_filter 的優先級(priority)參數是做什麼的?
WordPress Hooks 的運作原理是什麼?
訂閱免費電子報
把 AI 自動化、企業系統設計與 WordPress / Laravel 開發的真實案例和可直接照做的技巧,整理成電子報寄給你。只寄精選內容、不灌垃圾信,一鍵就能退訂。