Skip to content

REST API 开发

REST API 概述

WordPress REST API 提供了一种标准方式与 WordPress 进行交互,支持创建、读取、更新、删除(CRUD)操作。

基础端点

http://yoursite.com/wp-json/wp/v2/

常用端点

端点方法说明
/wp/v2/postsGET获取文章列表
/wp/v2/posts/{id}GET/POST/PUT/DELETE单篇文章操作
/wp/v2/pagesGET获取页面列表
/wp/v2/categoriesGET获取分类列表
/wp/v2/tagsGET获取标签列表
/wp/v2/usersGET获取用户列表
/wp/v2/mediaGET获取媒体列表
/wp/v2/settingsGET/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>
  );
}

认证方式

适用于同域名 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 最佳实践

  1. 使用命名空间 - 避免与其他插件冲突
  2. 添加权限检查 - 保护敏感操作
  3. 使用 WP_Error - 返回有意义的错误
  4. 注册 Schema - 提供清晰的文档
  5. 使用 prepare_item_for_response - 统一响应格式
  6. 添加分页支持 - 处理大量数据
  7. 添加过滤参数 - 提高 API 灵活性

基于 WordPress官方文档 构建