WordPress 只能寫文章?錯!資深工程師手把手教你用 REST API 自訂端點,打造無頭應用超能力!
嗨,我是浪花科技的 Eric。身為一個整天跟程式碼打交道的資深工程師,我最常聽到對 WordPress 的一個誤解就是:「啊,那不就是個寫部落格的工具嗎?」每次聽到這個,我的白眼都快翻到後腦勺了。拜託,都什麼年代了!WordPress 早就不只是一個 CMS(內容管理系統),它是一個功能強大的應用程式框架(Application Framework)。而解放這股力量的關鍵鑰匙,就是今天的主角——WordPress REST API。
或許你已經用過別人寫好的外掛來串接 API,但那種隔靴搔癢的感覺,工程師都懂。如果你想讓 WordPress 真正成為你專案的後端大腦,能夠與你的手機 App、前端框架(React、Vue)、甚至各種自動化工具無縫溝通,那麼學會如何進行 WordPress REST API 自訂端點開發,就是你非點不可的技能樹。這篇文章不是那種複製貼上就結束的教學,我會帶你從核心觀念拆解,到實際動手寫一個有用的端點,並穿插一些工程師的龜毛堅持,特別是在安全性方面。準備好了嗎?讓我們開始解放 WordPress 的真正潛力!
為什麼你需要 WordPress REST API 自訂端點?
在我們一頭栽進程式碼之前,先搞清楚「為什麼」要做這件事。不然寫了半天,結果發現用外掛點幾下就能解決,那不是很糗嗎?(雖然身為工程師,我們有時就是享受那個造輪子的過程啦…)
解放你的前端框架 (Headless CMS)
這大概是目前最潮、也最實用的應用場景了。所謂的「無頭 CMS (Headless CMS)」,就是把 WordPress 當成一個純粹的後端資料庫跟後台管理介面,而前端的「頭」(也就是使用者看到的網站畫面)則是用 React、Vue、Svelte 或 Next.js 這些現代化的 JavaScript 框架來打造。這樣做的好處是前後端分離,前端可以做到極致的效能和使用者體驗,後端則專注在內容管理。而連接這兩者的橋樑,就是 REST API。雖然 WordPress 內建了許多預設端點(例如取得文章、頁面),但你很快就會發現,你需要一些更客製化的資料格式,這時就得靠自訂端點來完成了。
打造專屬的自動化流程
想像一下,當你的 WooCommerce 商店有一筆新訂單時,你希望不只是發一封 Email,還想同時把訂單資料拋送到你的會計系統、更新 Google Sheets 庫存表,並觸發一條 LINE 通知給倉管人員。這些複雜的流程,光靠現成外掛很難兜起來。但透過自訂的 REST API 端點,你可以設計一個專門接收訂單 ID 的端點,然後在後端執行所有你需要的商業邏輯,再把結果回傳。像 n8n 或 Zapier 這類自動化工具,就能夠輕鬆地與你的自訂端點對接,打造出專屬於你公司的自動化帝國。
與外部系統的資料橋樑
很多企業內部都有自己的 ERP、CRM 或其他舊有系統。當你需要讓網站資料(例如會員註冊、表單提交)與這些系統同步時,自訂端點就是最穩固的橋樑。你可以建立一個端點,專門接收來自內部系統的指令來更新網站內容;反之,也可以在網站有特定事件發生時,透過自訂端點將資料整理成對方要的格式,再傳送出去。這遠比直接操作資料庫來得安全且有彈性。
核心武器:`register_rest_route` 函數深度解析
好了,說了這麼多,該來點硬核的了。在 WordPress 中,創造自訂端點的核心函數只有一個,就是 `register_rest_route()`。所有魔法都圍繞著它展開。這個函數必須掛載在 `rest_api_init` 這個 Action Hook 上。這點很重要,在錯的時機點執行,WordPress 可是不會理你的。這就是為什麼我常說,搞懂 WordPress 的 Hooks 運作機制,比你會寫多少花俏的程式碼還重要。
add_action( 'rest_api_init', 'roamer_tech_register_custom_routes' );
function roamer_tech_register_custom_routes() {
register_rest_route(
'my-awesome-api/v1', // 1. 命名空間 (Namespace)
'/author/(?P<id>\d+)', // 2. 路由 (Route)
array( // 3. 參數 (Arguments)
'methods' => 'GET',
'callback' => 'roamer_tech_get_author_posts_callback',
'permission_callback' => '__return_true', // 先別學這個壞習慣,等等會罵人
)
);
}
我們來把這個函數的三個主要參數拆開來看:
第一個參數:`$namespace` (命名空間)
命名空間就像是你的 API 的姓氏,用來區分你的 API 和其他外掛或 WordPress 核心的 API。格式通常是 `vendor/v1`,例如 `roamer-tech/v1`。`vendor` 通常是你的公司或外掛名稱,`v1` 則是版本號。拜託,千萬不要亂取,也一定要加上版本號!未來如果你的 API 需要大改版,才不會影響到舊有的應用,直接推出 `v2` 版本就好。這是專業工程師的基本素養。
第二個參數:`$route` (路由)
路由就是端點的具體路徑,它會接在命名空間後面,例如 `/latest-posts` 或 `/product/(?P<id>\d+)`。你可以看到後面這個例子有點特別,它用到了正規表示法(Regular Expression)。這是在路由中定義參數的方式,`(?P<id>\d+)` 的意思是「捕獲一個名為 `id` 的參數,且這個參數必須是一個或多個數字」。這樣一來,我們就可以在後續的 callback 函式中,透過 `id` 這個名字來取得傳入的數字(例如文章 ID 或產品 ID)。
第三個參數:`$args` (陣列參數)
這才是重頭戲,它是一個陣列,裡面定義了這個端點的行為。最重要的鍵值有:
- `methods`: 定義這個端點接受的 HTTP 請求方法。可以是 `GET`(取得資料)、`POST`(新增資料)、`PUT`/`PATCH`(更新資料)、`DELETE`(刪除資料)。也可以是一個陣列,例如 `[‘POST’, ‘PUT’]`。
- `callback`: 指定當這個端點被呼叫時,要執行的 PHP 函式。所有的資料處理、查詢、計算都在這個函式裡完成。這個函式必須回傳一個值,通常是陣列或物件,WordPress 會自動幫你轉換成 JSON 格式。更專業的做法是回傳一個 `WP_REST_Response` 物件。
- `permission_callback`: 權限回呼函式,這是你的 API 的保全。它會在 `callback` 執行之前被呼叫,用來檢查目前的使用者是否有權限存取這個端點。這個函式必須回傳 `true` 或 `false`。我再強調一次,絕對、絕對不要為了方便直接寫 `__return_true`,除非你很確定這是一個完全公開的資料!這跟把家裡鑰匙掛在門上沒兩樣。
- `args`: 用來定義這個端點可以接受哪些 URL 參數(Query Parameters)。你可以在這裡定義每個參數的預設值、是否為必要、以及最重要的——驗證(validation)和淨化(sanitization)的回呼函式。
實戰演練:打造一個「取得最新文章摘要」的自訂端點
光說不練假把戲,我們來動手做一個簡單但實用的端點。目標是建立一個 `GET` 端點 `/roamer-tech/v1/latest-posts`,它會回傳網站最新的 3 篇文章,但不是回傳所有亂七八糟的欄位,而是只回傳我們精選過的:文章標題、摘要、以及連結。
步驟一:在 `functions.php` 註冊路由
把這段程式碼加到你的子佈景主題的 `functions.php` 檔案,或是一個你自訂的外掛檔案中。
add_action( 'rest_api_init', function () {
register_rest_route( 'roamer-tech/v1', '/latest-posts', array(
'methods' => 'GET',
'callback' => 'roamer_tech_get_latest_posts_callback',
'permission_callback' => 'roamer_tech_api_permission_check',
) );
} );
步驟二:撰寫 `callback` 回呼函式
這個函式負責查詢資料庫,並整理成我們想要的格式。這裡我們使用 `WP_Query` 來取得文章,然後用一個迴圈把資料塞進陣列。最後,我們會用 `WP_REST_Response` 來回傳資料,這是一個好習慣,因為它可以讓我們自訂 HTTP 狀態碼,例如成功時回傳 200。
function roamer_tech_get_latest_posts_callback( WP_REST_Request $request ) {
$args = array(
'post_type' => 'post',
'posts_per_page' => 3,
'post_status' => 'publish',
);
$query = new WP_Query( $args );
$posts_data = array();
if ( $query->have_posts() ) {
while ( $query->have_posts() ) {
$query->the_post();
$posts_data[] = array(
'title' => get_the_title(),
'excerpt' => get_the_excerpt(),
'link' => get_permalink(),
);
}
wp_reset_postdata();
}
// 使用 WP_REST_Response 回傳,更標準的做法
return new WP_REST_Response( $posts_data, 200 );
}
看看我們回傳的資料,是不是比 WordPress 預設的乾淨多了?只給前端需要的東西,這能有效減少傳輸量,提升效能。
步驟三:加上 `permission_callback` 權限檢查
現在來處理最重要的權限問題。因為我們的端點只是讀取公開的文章,所以我們可以簡單地回傳 `true`,代表任何人都可以存取。但即使是這樣,我也建議你把它寫成一個獨立的函式,而不是直接用 `__return_true`。這樣未來如果需求變更,你只要修改這個函式就好。
function roamer_tech_api_permission_check() {
// 這個端點是公開的,所以我們直接回傳 true
// 如果是需要登入才能存取的資料,你應該要用 current_user_can()
// 例如: return current_user_can( 'edit_posts' );
return true;
}
如果你要做的是一個需要登入使用者才能操作的端點(例如更新個人資料),你的權限檢查就應該類似 `return current_user_can( ‘edit_user’, $user_id );` 這樣,去檢查目前的使用者是否有權限編輯指定 ID 的使用者資料。
安全性!安全性!安全性!工程師的囉嗦時間
如果前面的內容你都看懂了,恭喜你已經入門了。但如果你想成為一個可靠的工程師,那接下來的內容你必須刻在腦子裡。一個不安全的 API 端點,絕對是整個網站最大的資安漏洞,沒有之一。
權限檢查是你的第一道防線
我已經講了八百次了,`permission_callback` 是你的神主牌。設計任何端點前,第一個要問自己的問題就是:「誰可以存取它?」是所有人?只有登入的使用者?還是只有管理員?然後根據這個問題,用 WordPress 內建的權限系統(Capabilities)去寫你的 `permission_callback`。檢查權限,而不是檢查角色(Role)。
驗證與淨化 (Validation and Sanitization)
「永遠不要相信來自客戶端的任何資料」,這句話應該裱框掛在每個工程師的桌前。當你的端點接受參數時(不論是 URL 參數還是 POST body),你都必須做兩件事:
- 驗證 (Validation): 檢查傳進來的資料格式是否正確。例如,需要數字 ID 的地方,來的卻是字串,那就該直接拒絕請求。
- 淨化 (Sanitization): 清理傳進來的資料,移除任何潛在的惡意程式碼(例如 JavaScript 或 SQL Injection 語法)。
WordPress 提供了很多好用的函式,像是 `sanitize_text_field()`、`sanitize_email()`、`absint()`(確保是正整數)等等,請務必善用它們。
Nonces 的使用時機
如果你開發的端點是給「已經登入 WordPress 後台的使用者」透過前端腳本來操作的(例如在後台點一個按鈕,透過 AJAX 呼叫你的 API),那你必須使用 Nonces 來驗證請求,以防止 CSRF(跨站請求偽造)攻擊。簡單來說,Nonce 就像一個一次性的密碼,確保請求是從你的網站發出的,而不是駭客偽造的。關於 Nonces 的詳細攻防,可以參考這篇《你的表單安全嗎?揭開 WordPress Nonces 的神秘面紗》。
偵錯與測試你的自訂端點
寫完 API 之後,你總得測試它吧?我個人推薦使用 Postman 或 Insomnia 這類的 API 測試工具。它們可以讓你很方便地發送 GET、POST 等各種請求,並查看回傳的 Header 和 Body 內容。
如果你的端點回傳 500 錯誤或是一片空白,八成是你的 PHP 程式碼有錯。請打開 WordPress 的除錯模式(在 `wp-config.php` 中設定 `define( ‘WP_DEBUG’, true );` 和 `define( ‘WP_DEBUG_LOG’, true );`),然後去檢查 `wp-content` 資料夾下的 `debug.log` 檔案,通常錯誤訊息都會在那裡。
在您深入 REST API 的世界之前,打好基礎非常重要。這裡有幾篇文章,可以幫你把相關的武功練得更扎實:
- API 亂糟糟,專案火葬場?資深工程師的 WordPress REST API 設計聖經 (REST + JSON)
- 你的表單安全嗎?揭開 WordPress Nonces 的神秘面紗,杜絕 CSRF 攻擊的終極防線!
- Action vs. Filter 大亂鬥?資深工程師帶你拆解 WordPress Hooks 底層邏輯,別再搞混了!
今天我們從觀念到實作,走了一遍 WordPress REST API 自訂端點開發 的流程。這只是個開始,REST API 的世界非常廣闊,你可以結合文章後設資料 (meta fields)、使用者權限、甚至是 WooCommerce 的訂單資料,打造出無比強大的應用。當你掌握了這個技能,WordPress 在你手中就不再只是一個網站,而是一個充滿無限可能的後端服務器。
如果你在開發過程中遇到瓶頸,或是你的專案需要更複雜、更高效能的客製化 API 解決方案,別忘了浪花科技的工程師團隊隨時都在這裡。我們專門處理各種 WordPress 的疑難雜症。歡迎點擊這裡,填寫表單聯繫我們,讓我們聊聊如何讓你的網站發揮 120% 的潛力!
常見問題 (FAQ)
Q1: WordPress REST API 的命名空間 (namespace) 和路由 (route) 有什麼不同?
A1: 您可以把「命名空間」想像成 API 的群組名稱或姓氏,例如 `my-plugin/v1`,它用來區分不同外掛或版本的 API,避免衝突。「路由」則是該群組下的具體路徑或名字,例如 `/posts` 或 `/settings`。完整的 API 端點 URL 會是 `https://yourdomain.com/wp-json/my-plugin/v1/posts`,結合了網域、API 基礎路徑、命名空間和路由。
Q2: 為什麼 `permission_callback` 這麼重要?不能直接跳過嗎?
A2: 絕對不行!`permission_callback` 是您 API 的安全守門員。如果沒有它,或設定不當(例如直接回傳 true),任何知道您端點 URL 的人都可以存取它。對於讀取公開資料的端點或許還好,但如果是涉及寫入、修改、刪除資料或讀取敏感資訊(如使用者資料、訂單)的端點,缺少權限檢查會導致嚴重的資安漏洞,等於是將您網站的後門大開。
Q3: 我需要在每個自訂端點都使用 Nonce 嗎?
A3: 不一定。Nonce 的主要目的是防止 CSRF(跨站請求偽造)攻擊,它驗證的是「請求的發起者是否合法」。因此,它主要用於需要「已登入使用者」進行操作的場景,例如使用者在 WordPress 後台點擊按鈕觸發的 API 請求。如果您的 API 是設計給外部系統、手機 App 或公開的前端網站使用的(這些情境通常使用 API Key 或 OAuth 等方式進行認證),那麼 Nonce 就不是必要的。
Q4: 我要如何傳遞參數到我的自訂端點?
A4: 有幾種常見的方式:1. URL 參數:將參數直接放在路由中,例如 `/author/(?P<id>\d+)`,可以從 `$request[‘id’]` 取得。2. Query String 參數:放在 URL 的問號後面,例如 `/latest-posts?count=5`,可以從 `$request->get_param(‘count’)` 取得。3. POST/PUT Body:對於新增或更新資料的請求,可以將資料放在請求的 Body 中(通常是 JSON 格式),並用 `$request->get_json_params()` 來取得。不論哪種方式,都務必要在後端進行嚴格的驗證與淨化。






