iT邦幫忙

2023 iThome 鐵人賽

DAY 18
0
WordPress

從 0 到 100:WordPress 開發者的實戰手冊系列 第 18

Day 18 - WordPress 的 REST API 設計與應用

  • 分享至 

  • xImage
  •  

在昨天的文章裡,筆者和大家分享 WordPress 如何透過 admin-ajax.php 以及動態鉤點的運用,瞭解如何在不重新加載整個頁面的情況下,實現從後端取得資料並更新部分網頁內容的流程。

除了 WordPress 傳統的 AJAX 機制以外,還有另一個方式可以達成前後端的資料交換,也是今天要分享的章節— WordPress REST API。

什麼是 REST

REST(Representational State Transfer, 表現狀態轉移)形式的 API 提供了一種具有靈活性的方法,便於開發者處理和應用程式相資料關聯的物件 (object) 和集合 (collection)。它是一種軟體設計的概念,不是一種硬性的規範,使用這種概念來設計的 API 也稱為 RESTful API。

以 WordPress REST API 為例,每一個端點都與 WordPress 中的特定資料類型(例如:文章、頁面、分類等)相關聯。開發者能夠透過 HTTP 協定,利用這些端點來傳送和接收JSON 格式的資料,從而在 WordPress 網站上執行內容的新增、修改、查詢、刪除等各種操作。

REST 風格的 API 使用 JSON 格式傳遞、接收資料,主要是由於JSON的資料結構既簡單又輕量,不僅便於人們閱讀,也方便機器解析。而且 JSON 在各種程式語言受到廣泛的支援及應用,無論是 Web 還是行動裝置上的 App,都可以透過 JSON 格式的資料交換,開發和 WordPress 互動的應用程式。

和 WordPress 傳統的 AJAX 區別

WordPress AJAX

WordPress AJAX
圖:AJAX 流程

使用 admin_ajax.php 作為 AJAX 的資料入口的定義方式和 WordPress 定義 REST 的方式有很大的區別。前者利用傳數的參數 actionwp_ajax_wp_ajax_nopriv_ 兩組字串,結合成動態鉤點,以執行註冊在該鉤點中的程式。

WordPress REST

WordPress REST API
圖:REST 流程

後者則透過 register_rest_route 函式定義端點、處理的回呼函式,並註冊到 rest_api_init 鉤點。當 WordPress 接收到網址為該定義的端點時,則執行回呼函式,函式處理後回應 JSON 格式的資料。

當然,設計好的 REST API 也可以作為 AJAX 使用,不過相較於傳統使用 admin_ajax.php 作為 AJAX 的資料入口的作法,還是有很大的區別。

  1. 定義的方法不同,AJAX 使用動態鉤點,REST 必須定義端點。
  2. 回應給客戶端的資料結構不同,AJAX 無限制, REST 一定要回傳 JSON。
  3. WordPress 載入流程不同。雖然都會載入 WordPress 核心,但執行期間會經過的鉤點和其生命週期不同,因此設計時要註冊的鉤點要注意是否為如預期般地觸發。

使用 WordPress 內建的 REST 端點

以下為 WordPress 內建的 REST 端點,可以點擊資源名稱上的連結查看官方文件。

資源名稱 端點 說明
Posts /wp/v2/posts 管理網站上的文章,包括查詢、新增、刪除和更新文章。
Post Revisions /wp/v2/posts/<id>/revisions 提供文章的修訂版本的存取能力,允許開發者檢索過去的文章版本。
Categories /wp/v2/categories 管理文章的分類,包括新增、刪除和更新分類。
Tags /wp/v2/tags 管理和查詢文章的標籤,允許加上新標籤並讀取、更新或刪除現有的標籤。
Pages /wp/v2/pages 處理網站的靜態頁面,包括新增、更新、刪除和查詢頁面。
Page Revisions /wp/v2/pages/<id>/revisions 用於查詢和管理頁面的修訂版本、查看過去的頁面版本。
Comments /wp/v2/comments 查詢和管理文章和頁面的評論,包括發布新評論和修改或刪除現有迴響。
Taxonomies /wp/v2/taxonomies 提供對文章的分類法的存取和管理,包括查詢已定義的分類法詳情。
Media /wp/v2/media 管理和查詢媒體項目,例如圖片和影片,包括上傳新媒體和查詢、更新或刪除現有媒體。
Users /wp/v2/users 管理和查詢用戶資訊,包括新增新用戶、查詢、更新或刪除現有用戶。
Post Types /wp/v2/types 提供對網站上定義的文章類型的存取,允許開發者查詢有關這些類型的詳細資訊。
Post Statuses /wp/v2/statuses 允許開發者查詢和管理文章的可能狀態(例如草稿已發布)。
Settings /wp/v2/settings 提供對網站設定的管理和存取,允許讀取和更新網站的核心設定。
Themes /wp/v2/themes 查詢和更改當前啟用的佈景主題的資訊,也可以查詢可用主題的列表。
Search /wp/v2/search 允許通過 REST API 搜尋網站內容,提供與現有 WordPress 搜尋功能相似的功能。
Block Types /wp/v2/block-types 提供有關註冊區塊類型的資訊的存取,這些區塊類型可用於編輯文章和頁面。
Blocks /wp/v2/blocks 管理和查詢可重用的塊,這些區塊可以在多個文章和頁面之間共享。
Block Revisions /wp/v2/blocks/<id>/autosaves/ 允許開發者查詢和管理可重用區塊的修訂版本,提供對過去的區塊版本的存取。
Block Renderer /wp/v2/block-renderer 渲染區塊的內容,讓開發者能以程式化的方式查詢區塊的 HTML 輸出。
Block Directory Items /wp/v2/block-directory/search 允許搜尋可用的區塊目錄項目,為使用者提供一個界面來搜尋和安裝新的區塊。
Plugins /wp/v2/plugins 提供對安裝的外掛的管理和存取,允許開發者查詢有關已安裝外掛的資訊,以及啟用或停用它們。

藉由這些已經內建的 REST API,我們甚至可以直接拿來打造一個 SPA (Single-page application, 單頁式應用程式)式的網頁,或者其它技術來打造全新的網站,例如使用 Next.js 搭配 React,而完全不用 PHP 當作前台,僅僅使用 WordPress 當作後台及資料管理之用,酷吧!

使用 Postman 測試

Postman 上的 WordPress API 範本集合
圖:Postman 上的 WordPress API 集合

關於內建的 REST API,我們大可不必一個一個 API 上官方網站去查詢文件,在 Postman 有熱心的開發者建立了 WordPress 的 API 集合,例如:這裡,我們可以直接 fork 到我們的 Postman 帳號上,接著設定好相關的環境變數,將 URL 變數設成自己的開發環境,就可以開始把玩每一支 API 了。

在下一個段落介紹如何設計 REST API,測試的工作也交給 Postman,有系統性地進行開發。

設計 REST API

比起前一篇文章的 AJAX 方法簡潔許多。使用到一個鉤點和一個 WordPress 函式。

  • 鉤點:rest_api_init
  • 函式:register_rest_route

示範用的程式片段
圖:示範用的程式片段 Gist

第 6 至 10 行:處理該 REST 端點進來的資料用的函式。
第 18 至 29 行:註冊 API 的端點路由。
第 22 行:命名空間。
第 25 行:HTTP 請求的類型。
第 26 行:回呼函式的名稱。
第 31 行:註冊到 rest_api_init 鉤點。

測試結果

Postman 測試結果
圖:Postman 測試結果

開啟 Postman 打看看,該 REST API 是否接通。

安全性

當有些功能必須限制權限時,該怎麼做?

在 register_rest_route 函式的第三個參數是一個選項陣列。在該陣列中的 permission_callback 欄位可以定義一個權限控制的回呼函式,如下:

示範用的程式片段
圖:示範用的程式片段

第 15 至 17 行:定義一個回呼函式,回傳值為布林值,來判斷這次的請求要允許還是拒決。

測試結果

Postman 測試結果
圖:Postman 測試結果

取得當前登入使用者資訊

依照 REST 風格的 API 設計概念來說,API 都應該是無狀態的 (stateless)。簡單的說,就是 API 的資料傳入和輸出都不應該會被其它狀態影響,例如 Cookie。

正確的作法是採用 Oauth 或 JWT 認證,這樣做的話才能達到不管是 Web 也好, 行動裝置上的 App 也好,在存取 API 的行為是一致的。

雖說如此,或許是為了降低 WordPress REST 的使用技術門檻,仍支援傳統的 session cookie 的方式取得登入的使用者資料。只要在發起請求的 header 資訊中加上 X-WP-Nonce 欄位,或者請求主題的欄位中有 _wpnonce 欄位。

如何取得 nonce 值?

傳給 REST API 所需的 nonce 來自以下方法:

wp_create_nonce( 'wp_rest' ); // 只能是 wp_rest

有兩種方法可以取得夠過上述函式產生的 REST 專用 nonce。

  • 可以把這個 nonce 輸出到網頁中取得
  • 建立一個傳統 AJAX 來取得。

測試範例

Postman 測試結果
動圖:Postman 測試傳入 nonce

當 WordPress 的 REST API 有取得 nonce 進行驗證,和使用者相關的函式才會正常運作,這些函式包括但不限於:

  • is_user_logged_in
  • get_current_user_id
  • current_user_can
  • 等等...。

如果想要全平台都可以共用同一個 API 的話,建議可以避免使用 Cookie 驗證,改用其它驗證機制。

總結

今天寫了落落長,最後總結一下 WordPress 中的兩種資料交換機制:傳統的 AJAX 方法以及 WordPress REST API。前者藉由 admin-ajax.php 和動態鉤點,而後者則提供一個較為直覺且結構化的方法。

雖然傳統的 AJAX 方法有其便利之處,但從長遠的角度和跨平台的可用性來看,REST API 提供了更多的靈活性和擴展性唷。

參考官方文件:


課後思考:

筆者曾看過為了繞過 WordPress 的 nonce 機制,而在自己的 REST API 設計上初始化時,直接取用核心取得 Cookie 並登入的那一段邏輯來用。這樣的作法,你覺得這樣做有什麼優點?有什麼缺點?

前篇解答參考:

網站上常見的往下滑動自動換頁生成下一頁的內容、網站即時聊天、互動式投票等等。都是一些常見的使用 AJAX 的網站功能例子,透過這些應用,提供更流暢的用戶體驗。


上一篇
Day 17 - WordPress 的 AJAX 設計與應用
下一篇
Day 19 - 詳解 WordPress 的使用者角色與權限控管
系列文
從 0 到 100:WordPress 開發者的實戰手冊30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
帶我飛
iT邦新手 5 級 ‧ 2023-10-25 16:30:23

大大你好:
我使用POSTMAN代入_wpnonce會出現403,需要做其他設定嗎?

{
  "code": "rest_cookie_invalid_nonce",
  "message": "Cookie 檢查失敗",
  "data": {
      "status": 403
  }
}

使用twenty-twenty-one新增按鈕,使用JS發送ajax則會成功。
http://localhost/wordpress/wp-json/ironman/v1/say_hi

Terry L. iT邦研究生 4 級 ‧ 2023-10-26 10:58:39 檢舉

確認 _wpnonce 接收的值是由 wp_create_nonce( 'wp_rest' ); 產生的,不能用我的範例的值,再試試。

帶我飛 iT邦新手 5 級 ‧ 2023-11-22 14:59:42 檢舉

似乎是使用POSTMAN發請求而網站不知道登入者是誰,後來依此網站教學,設定Cookie有成功了。
https://dev.to/david_woolf/using-postman-with-the-wordpress-rest-api-41bk

我要留言

立即登入留言