編寫端點時,使用控制器類來處理端點的功能是有幫助的。控制器類將提供與API進行交互的標準方式,也是與API進行交互的更可維護的方式。 WordPress目前的最低PHP版本為5.2,如果您正在開發將由WordPress生態系統使用的端點,您應該考慮支持WordPress的最低要求。
PHP 5.2沒有內置命名空間。這意味著您聲明的每個函數都將在全局范圍內。如果您決定使用get_items()等端點的常用函數名稱,另一個插件也會注冊該函數,則PHP將失敗并導致致命錯誤。這是因為函數get_items()被聲明為兩次。通過封裝我們的端點,我們可以避免這些命名沖突,并具有與API進行交互的一致方式。
##控制器
控制器通常做一件事情;他們接收輸入并產生輸出。對于WordPress REST API,我們的控制器將處理作為WP_REST_Request對象的請求輸入,并將響應輸出生成為WP_REST_Response對象。我們來看一個例子的控制器類:
```
class My_REST_Posts_Controller {
// Here initialize our namespace and resource name.
public function __construct() {
$this->namespace = '/my-namespace/v1';
$this->resource_name = 'posts';
}
// Register our routes.
public function register_routes() {
register_rest_route( $this->namespace, '/' . $this->resource_name, array(
// Here we register the readable endpoint for collections.
array(
'methods' => 'GET',
'callback' => array( $this, 'get_items' ),
'permission_callback' => array( $this, 'get_items_permissions_check' ),
),
// Register our schema callback.
'schema' => array( $this, 'get_item_schema' ),
) );
register_rest_route( $this->namespace, '/' . $this->resource_name . '/(?P<id>[\d]+)', array(
// Notice how we are registering multiple endpoints the 'schema' equates to an OPTIONS request.
array(
'methods' => 'GET',
'callback' => array( $this, 'get_item' ),
'permission_callback' => array( $this, 'get_item_permissions_check' ),
),
// Register our schema callback.
'schema' => array( $this, 'get_item_schema' ),
) );
}
/**
* Check permissions for the posts.
*
* @param WP_REST_Request $request Current request.
*/
public function get_items_permissions_check( $request ) {
if ( ! current_user_can( 'read' ) ) {
return new WP_Error( 'rest_forbidden', esc_html__( 'You cannot view the post resource.' ), array( 'status' => $this->authorization_status_code() ) );
}
return true;
}
/**
* Grabs the five most recent posts and outputs them as a rest response.
*
* @param WP_REST_Request $request Current request.
*/
public function get_items( $request ) {
$args = array(
'post_per_page' => 5,
);
$posts = get_posts( $args );
$data = array();
if ( empty( $posts ) ) {
return rest_ensure_response( $data );
}
foreach ( $posts as $post ) {
$response = $this->prepare_item_for_response( $post, $request );
$data[] = $this->prepare_response_for_collection( $response );
}
// Return all of our comment response data.
return rest_ensure_response( $data );
}
/**
* Check permissions for the posts.
*
* @param WP_REST_Request $request Current request.
*/
public function get_item_permissions_check( $request ) {
if ( ! current_user_can( 'read' ) ) {
return new WP_Error( 'rest_forbidden', esc_html__( 'You cannot view the post resource.' ), array( 'status' => $this->authorization_status_code() ) );
}
return true;
}
/**
* Grabs the five most recent posts and outputs them as a rest response.
*
* @param WP_REST_Request $request Current request.
*/
public function get_item( $request ) {
$id = (int) $request['id'];
$post = get_post( $id );
if ( empty( $post ) ) {
return rest_ensure_response( array() );
}
$response = prepare_item_for_response( $post );
// Return all of our post response data.
return $response;
}
/**
* Matches the post data to the schema we want.
*
* @param WP_Post $post The comment object whose response is being prepared.
*/
public function prepare_item_for_response( $post, $request ) {
$post_data = array();
$schema = $this->get_item_schema( $request );
// We are also renaming the fields to more understandable names.
if ( isset( $schema['properties']['id'] ) ) {
$post_data['id'] = (int) $post->ID;
}
if ( isset( $schema['properties']['content'] ) ) {
$post_data['content'] = apply_filters( 'the_content', $post->post_content, $post );
}
return rest_ensure_response( $post_data );
}
/**
* Prepare a response for inserting into a collection of responses.
*
* This is copied from WP_REST_Controller class in the WP REST API v2 plugin.
*
* @param WP_REST_Response $response Response object.
* @return array Response data, ready for insertion into collection data.
*/
public function prepare_response_for_collection( $response ) {
if ( ! ( $response instanceof WP_REST_Response ) ) {
return $response;
}
$data = (array) $response->get_data();
$server = rest_get_server();
if ( method_exists( $server, 'get_compact_response_links' ) ) {
$links = call_user_func( array( $server, 'get_compact_response_links' ), $response );
} else {
$links = call_user_func( array( $server, 'get_response_links' ), $response );
}
if ( ! empty( $links ) ) {
$data['_links'] = $links;
}
return $data;
}
/**
* Get our sample schema for a post.
*
* @param WP_REST_Request $request Current request.
*/
public function get_item_schema( $request ) {
$schema = array(
// This tells the spec of JSON Schema we are using which is draft 4.
'$schema' => 'http://json-schema.org/draft-04/schema#',
// The title property marks the identity of the resource.
'title' => 'post',
'type' => 'object',
// In JSON Schema you can specify object properties in the properties attribute.
'properties' => array(
'id' => array(
'description' => esc_html__( 'Unique identifier for the object.', 'my-textdomain' ),
'type' => 'integer',
'context' => array( 'view', 'edit', 'embed' ),
'readonly' => true,
),
'content' => array(
'description' => esc_html__( 'The content for the object.', 'my-textdomain' ),
'type' => 'string',
),
),
);
return $schema;
}
// Sets up the proper HTTP status code for authorization.
public function authorization_status_code() {
$status = 401;
if ( is_user_logged_in() ) {
$status = 403;
}
return $status;
}
}
// Function to register our new routes from the controller.
function prefix_register_my_rest_routes() {
$controller = new My_REST_Posts_Controller();
$controller->register_routes();
}
add_action( 'rest_api_init', 'prefix_register_my_rest_routes' );
```
## 概述與未來
控制器類在開發端點時為我們解決兩個大問題;缺乏命名空間和一致的結構。重要的是要注意,你不應濫用你的端點的繼承。例如:如果您為一個帖子端點編寫了一個控制器類,就像上面的例子,并且也希望支持自定義的帖子類型,你不應該這樣擴展My_REST_Posts_Controller:class My_CPT_REST_Controller extends My_REST_Posts_Controller。
相反,您應該創建一個完全獨立的控制器類,或者使My_REST_Posts_Controller處理所有可用的post類型。當你開始繼承遺產的路徑時,重要的是要明白,如果父類有必要在任何時候改變,而你的子類依賴于它們,那么你將會很頭痛。在大多數情況下,您將要創建基控制器類作為接口或抽象類,每個端點控制器都可以實現或擴展。抽象類方法在核心WordPress REST API端點內使用。
## 擴展內部類
WordPress REST API遵循其內部類的故意設計模式,可以將其分類為基礎架構或端點類。
基礎架構類支持端點類。他們處理WordPress REST API的邏輯,而不執行任何數據轉換。另一方面,端點類封裝了對WordPress資源執行CRUD操作所必需的功能邏輯。更具體地說,我們的基礎設施類包括WP_REST_Server和WP_REST_Request,我們的端點類包括WP_REST_Posts_Controller和WP_REST_Users_Controller。
讓我們深入了解每個基礎設施類的功能:
- WP_REST_Server:WordPress REST API的主控制器。路由被注冊到WordPress中的服務器。當調用WP_REST_Server服務請求時,它確定要調用哪個路由,并將路由回調傳遞給WP_REST_Request對象。 WP_REST_Server還處理身份驗證,并可執行請求驗證和權限檢查。
- WP_REST_Request:表示請求性質的對象。該對象包括請求詳細信息,如請求頭,參數和方法以及路由。它還可以執行請求驗證和消毒。
- WP_REST_Response:表示響應性質的對象。此類擴展了WP_HTTP_Response,其中包括頭文件,正文和狀態,并提供了一些輔助方法,如添加鏈接媒體的add_link(),以及用于獲取查詢導航標題的query_navigation_headers()。
所有端點類都擴展WP_REST_Controller。此類旨在表示操縱WordPress資源的一致模式。 WP_REST_Controller實現這些方法:
- register_routes():在第一次實例化類之后,調用register_routes()將資源的路由注冊到服務器。
- get_items():獲取現有實體的集合。
- get_item():獲取現有實體。如果實體不存在,則應返回HTTP錯誤代碼404。如果請求者沒有訪問實體的權限,則應返回HTTP錯誤代碼403。
- create_item():創建一個新的實體,給定一個有效的WP_REST_Request。如果創建成功,則應返回WP_REST_Response,HTTP status = 201,并將位置頭添加到新資源。如果以某種形式出現創建錯誤,則應返回適當的HTTP錯誤代碼和消息。
- update_item():給一個有效的WP_REST_Request更新現有實體。
- delete_item():刪除現有實體,給定一個有效的WP_REST_Request。如果以某種方式刪除錯誤,則應返回適當的HTTP錯誤代碼。
- get_items_permissions_check():在調用回調之前,檢查給定的請求是否具有資源集合的權限。
- get_item_permissions_check():在調用回調之前,檢查給定的請求是否具有獲取單個資源的權限。
- create_item_permissions_check():在調用回調之前,檢查給定的請求是否具有創建單個資源的權限。
- update_item_permissions_check():在調用回調之前,檢查給定的請求是否具有更新單個資源的權限。
- delete_item_permissions_check():在調用回調之前,檢查給定的請求是否具有刪除單個資源的權限。
- prepare_item_for_response():格式化一個資源以匹配它應該在響應中顯示。
- prepare_response_for_collection():當使用prepare_item_for_response()時,返回一個WP_REST_Response。這個幫助函數將所有這些響應包裝到一個集合中。
- filter_response_by_context():根據提供的上下文參數過濾響應形狀。
- get_item_schema():獲取資源的schema JSON Schema對象。
當與實現WP_REST_Controller的端點進行交互時,HTTP客戶端可以期望每個端點以類似的方式運行。
- 簡介
- 主題開發
- WordPress許可證
- 什么是主題
- 開發環境
- 主題開發示例
- 主題基礎
- 模板文件
- 主樣式表(style.css)
- 文章類型
- 規劃主題文件
- 模板層級
- 模板標簽
- 循環
- 主題函數
- 連接主題文件和目錄
- 使用CSS和JavaScript
- 條件標簽
- 類別,標簽和自定義分類
- 模板文件
- 內容模板文件
- 頁面模板文件
- 附件模板文件
- 自定義內容類型
- 部分和其他模板文件
- 評論模板
- 分類模板
- 404頁面
- 主題功能
- 核心支持的功能
- 管理菜單
- 自定義Headers
- 自定義Logo
- 文章格式
- 置頂文章
- Sidebars
- Widgets
- 導航菜單
- 分頁
- 媒體
- Audio
- Images
- Galleries
- Video
- 精選圖片和縮略圖
- 國際化
- 本地化
- 輔助功能
- 主題選項 – 自定義API
- 定制對象
- 改進用戶體驗的工具
- 定制JavaScript API
- JavaScript / Underscore.js渲染的自定義控件
- 高級用法
- 主題安全
- 數據消毒/逃避
- 數據驗證
- 使用隨機數
- 常見漏洞
- 高級主題
- 子主題
- UI最佳實踐
- JavaScript最佳做法
- 主題單元測試
- 驗證你的主題
- Plugin API Hooks
- 發布你的主題
- 所需的主題文件
- 測試
- 主題評論指南
- 寫文檔
- 提交你的主題到WordPress.org
- 參考文獻
- 模板標簽列表
- 條件標簽列表
- 編碼標準
- HTML編碼標準
- CSS編碼標準
- JavaScript編碼標準
- PHP編碼標準
- 插件開發
- 插件開發簡介
- 什么是插件
- 插件基礎
- 頭部要求
- 包括軟件許可證
- 啟用 / 停用 Hooks
- 卸載方法
- 最佳做法
- 插件安全
- 檢查用戶功能
- 數據驗證
- 保護輸入
- 保護輸出
- 隨機數
- Hooks
- Actions
- Filters
- 自定義Hooks
- 高級主題
- 管理菜單
- 頂級菜單
- 子菜單
- 短代碼
- 基本短碼
- 封閉短碼
- 帶參數的短代碼
- TinyMCE增強型短碼
- 設置
- 設置API
- 使用設置API
- 選項API
- 自定義設置頁面
- 元數據
- 管理帖子元數據
- 自定義元數據
- 渲染元數據
- 自定義文章類型
- 注冊自定義文章類型
- 使用自定義文章類型
- 分類
- 使用自定義分類
- 在WP 4.2+中使用“split術語”
- 用戶
- 創建和管理用戶
- 使用用戶元數據
- 角色和功能
- HTTP API
- JavaScript
- jQuery
- Ajax
- 服務器端PHP和入隊
- Heartbeat API
- 概要
- 計劃任務
- 了解WP-Cron計劃
- 安排WP-Cron 事件
- 將WP-Cron掛接到系統任務計劃程序中
- WP-Cron簡單測試
- 國際化
- 本地化
- 如何國際化您的插件
- 國際化安全
- WordPress.org
- 詳細插件指南
- 規劃您的插件
- 如何使用Subversion
- 插件開發者常見問題
- 開發工具
- Debug Bar 和附加組件
- 輔助插件
- REST API手冊
- 資源
- 文章
- 文章修訂
- 文章類型
- 文章狀態
- 類別
- 標簽
- 頁面
- 評論
- 分類
- 媒體
- 用戶
- 設置
- 使用REST API
- 全局參數
- 分頁
- 鏈接和嵌入
- 發現
- 認證
- 經常問的問題
- 骨干JavaScript客戶端
- 客戶端庫
- 擴展REST API
- 添加自定義端點
- 自定義內容類型
- 修改回應
- 模式
- 詞匯表
- 路由和端點
- 控制器類