REST API 开发
REST API 概述
WordPress REST API 提供了一种标准方式与 WordPress 进行交互,支持创建、读取、更新、删除(CRUD)操作。
基础端点
http://yoursite.com/wp-json/wp/v2/常用端点
| 端点 | 方法 | 说明 |
|---|---|---|
/wp/v2/posts | GET | 获取文章列表 |
/wp/v2/posts/{id} | GET/POST/PUT/DELETE | 单篇文章操作 |
/wp/v2/pages | GET | 获取页面列表 |
/wp/v2/categories | GET | 获取分类列表 |
/wp/v2/tags | GET | 获取标签列表 |
/wp/v2/users | GET | 获取用户列表 |
/wp/v2/media | GET | 获取媒体列表 |
/wp/v2/settings | GET/PATCH | 站点设置 |
启用 REST API
检查是否启用
php
<?php
// 检查 REST API 是否可用
rest_url(); // 返回 REST URL
// 检查特定路由
if (get_rest_url(null, 'wp/v2/posts')) {
// REST API 可用
}
// 或通过 header 检查
// X-WP-Total: 文章总数
// X-WP-TotalPages: 总页数
?>权限检查
php
<?php
// 获取当前用户权限状态
$user_id = get_current_user_id();
$can_read = current_user_can('read');
header('X-WP-Total: 100');
header('X-WP-TotalPages: 10');
?>注册自定义路由
基本路由注册
php
<?php
/**
* 注册自定义 REST API 路由
*/
add_action('rest_api_init', 'register_custom_routes');
function register_custom_routes() {
// 注册命名空间
$namespace = 'wp/v2';
// 注册路由
register_rest_route($namespace, '/books', array(
'methods' => 'GET',
'callback' => 'get_books',
'permission_callback' => '__return_true',
));
}
/**
* 获取书籍列表的回调
*/
function get_books($request) {
$books = array(
array(
'id' => 1,
'title' => 'WordPress 入门',
'author' => '张三',
),
array(
'id' => 2,
'title' => 'WordPress 高级开发',
'author' => '李四',
),
);
return new WP_REST_Response($books, 200);
}
?>带参数的路由
php
<?php
add_action('rest_api_init', 'register_book_routes');
function register_book_routes() {
register_rest_route('wp/v2', '/books', array(
array(
'methods' => 'GET',
'callback' => 'get_books',
'permission_callback' => '__return_true',
),
array(
'methods' => 'POST',
'callback' => 'create_book',
'permission_callback' => function() {
return current_user_can('edit_posts');
},
),
));
// 单本书籍路由
register_rest_route('wp/v2', '/books/(?P<id>\d+)', array(
'methods' => 'GET',
'callback' => 'get_single_book',
'args' => array(
'id' => array(
'validate_callback' => function($param) {
return is_numeric($param);
}
),
),
));
register_rest_route('wp/v2', '/books/(?P<id>\d+)', array(
'methods' => 'PUT',
'callback' => 'update_book',
'permission_callback' => function() {
return current_user_can('edit_posts');
},
));
register_rest_route('wp/v2', '/books/(?P<id>\d+)', array(
'methods' => 'DELETE',
'callback' => 'delete_book',
'permission_callback' => function() {
return current_user_can('delete_posts');
},
));
}
?>创建完整的 API 类
php
<?php
/**
* REST API 控制器类
*/
class WP_Books_Controller {
protected $namespace = 'wp/v2';
protected $rest_base = 'books';
/**
* 注册路由
*/
public function register_routes() {
register_rest_route($this->namespace, '/' . $this->rest_base, array(
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array($this, 'get_items'),
'permission_callback' => '__return_true',
'args' => $this->get_collection_params(),
),
array(
'methods' => WP_REST_Server::CREATABLE,
'callback' => array($this, 'create_item'),
'permission_callback' => array($this, 'create_item_permissions_check'),
'args' => $this->get_endpoint_args_for_item_schema(),
),
));
register_rest_route($this->namespace, '/' . $this->rest_base . '/(?P<id>[\d]+)', array(
'args' => array(
'id' => array(
'description' => '书籍 ID',
'type' => 'integer',
),
),
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array($this, 'get_item'),
'permission_callback' => '__return_true',
),
array(
'methods' => WP_REST_Server::EDITABLE,
'callback' => array($this, 'update_item'),
'permission_callback' => array($this, 'update_item_permissions_check'),
),
array(
'methods' => WP_REST_Server::DELETABLE,
'callback' => array($this, 'delete_item'),
'permission_callback' => array($this, 'delete_item_permissions_check'),
),
));
}
/**
* 获取书籍列表
*/
public function get_items($request) {
$args = array(
'post_type' => 'book',
'posts_per_page' => $request['per_page'] ?: 10,
'paged' => $request['page'] ?: 1,
);
if (isset($request['search'])) {
$args['s'] = $request['search'];
}
$query = new WP_Query($args);
$books = array();
foreach ($query->posts as $post) {
$books[] = $this->prepare_item_for_response($post, $request);
}
$response = new WP_REST_Response($books, 200);
$response->header('X-WP-Total', $query->found_posts);
$response->header('X-WP-TotalPages', ceil($query->found_posts / $args['posts_per_page']));
return $response;
}
/**
* 获取单本书籍
*/
public function get_item($request) {
$post_id = (int) $request['id'];
$post = get_post($post_id);
if (!$post || $post->post_type !== 'book') {
return new WP_Error(
'rest_post_invalid_id',
'无效的书籍 ID',
array('status' => 404)
);
}
return $this->prepare_item_for_response($post, $request);
}
/**
* 创建书籍
*/
public function create_item($request) {
$post_data = array(
'post_type' => 'book',
'post_title' => sanitize_text_field($request['title']),
'post_content' => wp_kses_post($request['description']),
'post_status' => $request['status'] ?: 'draft',
);
$post_id = wp_insert_post($post_data);
if (is_wp_error($post_id)) {
return $post_id;
}
// 保存自定义字段
if (isset($request['author'])) {
update_post_meta($post_id, 'book_author', sanitize_text_field($request['author']));
}
if (isset($request['price'])) {
update_post_meta($post_id, 'book_price', floatval($request['price']));
}
$post = get_post($post_id);
return $this->prepare_item_for_response($post, $request);
}
/**
* 更新书籍
*/
public function update_item($request) {
$post_id = (int) $request['id'];
$post = get_post($post_id);
if (!$post) {
return new WP_Error(
'rest_post_invalid_id',
'无效的书籍 ID',
array('status' => 404)
);
}
$post_data = array('ID' => $post_id);
if (isset($request['title'])) {
$post_data['post_title'] = sanitize_text_field($request['title']);
}
if (isset($request['description'])) {
$post_data['post_content'] = wp_kses_post($request['description']);
}
if (isset($request['status'])) {
$post_data['post_status'] = sanitize_key($request['status']);
}
wp_update_post($post_data);
// 更新自定义字段
if (isset($request['author'])) {
update_post_meta($post_id, 'book_author', sanitize_text_field($request['author']));
}
if (isset($request['price'])) {
update_post_meta($post_id, 'book_price', floatval($request['price']));
}
$post = get_post($post_id);
return $this->prepare_item_for_response($post, $request);
}
/**
* 删除书籍
*/
public function delete_item($request) {
$post_id = (int) $request['id'];
if (!wp_delete_post($post_id, true)) {
return new WP_Error(
'rest_cannot_delete',
'无法删除书籍',
array('status' => 500)
);
}
return array('deleted' => true, 'id' => $post_id);
}
/**
* 权限检查 - 创建
*/
public function create_item_permissions_check($request) {
return current_user_can('edit_posts');
}
/**
* 权限检查 - 更新
*/
public function update_item_permissions_check($request) {
$post = get_post((int) $request['id']);
return current_user_can('edit_post', $post->ID);
}
/**
* 权限检查 - 删除
*/
public function delete_item_permissions_check($request) {
$post = get_post((int) $request['id']);
return current_user_can('delete_post', $post->ID);
}
/**
* 准备响应数据
*/
public function prepare_item_for_response($post, $request) {
return array(
'id' => $post->ID,
'title' => $post->post_title,
'description' => $post->post_content,
'author' => get_post_meta($post->ID, 'book_author', true),
'price' => get_post_meta($post->ID, 'book_price', true),
'date' => mysql_to_rfc3339($post->post_date),
'status' => $post->post_status,
);
}
/**
* 获取集合参数
*/
public function get_collection_params() {
return array(
'page' => array(
'description' => '当前页码',
'type' => 'integer',
'default' => 1,
),
'per_page' => array(
'description' => '每页数量',
'type' => 'integer',
'default' => 10,
),
'search' => array(
'description' => '搜索关键词',
'type' => 'string',
),
);
}
}
// 初始化控制器
function init_books_controller() {
$controller = new WP_Books_Controller();
$controller->register_routes();
}
add_action('rest_api_init', 'init_books_controller');JavaScript 中使用 REST API
基础请求
javascript
// 获取文章列表
fetch('/wp-json/wp/v2/posts?per_page=10')
.then(response => response.json())
.then(data => console.log(data));
// 获取单篇文章
fetch('/wp-json/wp/v2/posts/1')
.then(response => response.json())
.then(post => {
console.log(post.title.rendered);
console.log(post.content.rendered);
});带认证的请求
javascript
// 使用 nonce(已登录用户)
fetch('/wp-json/wp/v2/posts', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-WP-Nonce': wpApiSettings.nonce // 后端提供
},
body: JSON.stringify({
title: '新文章标题',
content: '文章内容',
status: 'draft'
})
})
.then(response => response.json())
.then(data => console.log('创建成功:', data.id));WordPress 块编辑器中使用
javascript
import { select, dispatch } from '@wordpress/data';
import { apiFetch } from '@wordpress/api-fetch';
// GET 请求
const posts = await apiFetch({
path: '/wp/v2/posts?per_page=5'
});
// POST 请求
const newPost = await apiFetch({
path: '/wp/v2/posts',
method: 'POST',
data: {
title: '通过块编辑器创建的标题',
content: '内容...',
status: 'publish'
}
});React 组件示例
jsx
import { useState, useEffect } from 'react';
function PostsList() {
const [posts, setPosts] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch('/wp-json/wp/v2/posts?per_page=10')
.then(res => res.json())
.then(data => {
setPosts(data);
setLoading(false);
});
}, []);
if (loading) return <p>加载中...</p>;
return (
<ul>
{posts.map(post => (
<li key={post.id}>
<a href={post.link}>{post.title.rendered}</a>
</li>
))}
</ul>
);
}认证方式
1. Cookie 认证(默认)
适用于同域名 JavaScript:
javascript
// 页面已加载后自动可用
fetch('/wp-json/wp/v2/posts', {
credentials: 'include' // 包含 cookies
});2. Application Passwords
javascript
// 使用应用密码
const username = 'admin';
const password = 'xxxx xxxx xxxx xxxx xxxx xxxx';
fetch('/wp-json/wp/v2/posts', {
method: 'POST',
headers: {
'Authorization': 'Basic ' + btoa(username + ':' + password)
},
body: JSON.stringify({
title: '标题',
content: '内容'
})
});3. JWT 认证(需要插件)
javascript
// 安装 JWT Authentication for WP REST API 插件后
fetch('/wp-json/jwt-auth/v1/token', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
username: 'admin',
password: 'password'
})
})
.then(res => res.json())
.then(data => {
const token = data.token;
// 使用 token 请求
fetch('/wp-json/wp/v2/posts', {
headers: {
'Authorization': 'Bearer ' + token
}
});
});添加自定义字段到 API 响应
php
<?php
/**
* 将自定义字段注册到 REST API
*/
add_action('init', 'register_custom_meta');
function register_custom_meta() {
// 为 post 类型注册
register_post_meta('post', 'custom_field', array(
'show_in_rest' => true,
'single' => true,
'type' => 'string',
'auth_callback' => function() {
return current_user_can('edit_posts');
},
));
// 为所有帖子类型注册
$post_types = get_post_types(array('show_in_rest' => true), 'names');
foreach ($post_types as $post_type) {
register_post_meta($post_type, 'book_author', array(
'show_in_rest' => true,
'single' => true,
'type' => 'string',
));
}
}
?>修改现有 API 响应
php
<?php
/**
* 修改文章响应,添加自定义字段
*/
add_action('rest_api_init', 'add_custom_fields_to_api');
function add_custom_fields_to_api() {
register_rest_field('post', 'custom_author', array(
'get_callback' => function($post) {
return get_post_meta($post['id'], 'custom_author', true);
},
'update_callback' => function($value, $post) {
update_post_meta($post->ID, 'custom_author', sanitize_text_field($value));
},
'schema' => array(
'description' => '自定义作者',
'type' => 'string',
),
));
// 添加阅读时间估算
register_rest_field('post', 'reading_time', array(
'get_callback' => function($post) {
$content = $post['content']['raw'];
$word_count = str_word_count(strip_tags($content));
$reading_time = ceil($word_count / 200); // 假设每分钟 200 字
return $reading_time . ' 分钟';
},
'schema' => array(
'description' => '预计阅读时间',
'type' => 'string',
),
));
}
?>REST API 最佳实践
- 使用命名空间 - 避免与其他插件冲突
- 添加权限检查 - 保护敏感操作
- 使用 WP_Error - 返回有意义的错误
- 注册 Schema - 提供清晰的文档
- 使用 prepare_item_for_response - 统一响应格式
- 添加分页支持 - 处理大量数据
- 添加过滤参数 - 提高 API 灵活性
