WordPress 只能寫文章?錯!資深工程師手把手教你用 REST API 自訂端點,打造無頭應用超能力!

2025/09/15 | WP 開發技巧

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 之後,你總得測試它吧?我個人推薦使用 PostmanInsomnia 這類的 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 的世界之前,打好基礎非常重要。這裡有幾篇文章,可以幫你把相關的武功練得更扎實:

今天我們從觀念到實作,走了一遍 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()` 來取得。不論哪種方式,都務必要在後端進行嚴格的驗證與淨化。

 
立即諮詢,索取免費1年網站保固