WordPress REST API 为操作 WordPress 网站数据提供统一接口。本课介绍三种内部请求方式,并用 GET 请求获取公开自定义文章类型的数据。
Bookstore 插件
如果完成了“WordPress 插件入门”模块,你已经创建了注册 book 自定义文章类型的插件。跳过该模块时,可从原文的 Bookstore 插件链接下载 GitHub 代码。
安装并启用后,在编辑器中打开主插件文件,可以看到传给 register_post_type 的 show_in_rest:
$args = array(
'labels' => array(
'name' => 'Books',
'singular_name' => 'Book',
'menu_name' => 'Books',
'add_new' => 'Add New Book',
'add_new_item' => 'Add New Book',
'new_item' => 'New Book',
'edit_item' => 'Edit Book',
'view_item' => 'View Book',
'all_items' => 'All Books',
),
'public' => true,
'has_archive' => true,
'show_in_rest' => true,
'supports' => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt' ),
);
它为 true,表示该类型可通过 REST API 访问。打开 wp-json/wp/v2/book,就能看到相应数据。
函数参考还列出其他控制 REST 响应的参数,例如 rest_base 可修改路由。因为请求通常返回多本书,把它改成复数 books 更合适:
'show_in_rest' => true,
'rest_base' => 'books',
'supports' => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt' ),
之后就能通过 wp-json/wp/v2/books 访问图书。
发起 REST API 请求
假设希望在后台添加一个页面,获取图书并将标题和永久链接显示为逗号分隔列表。首先通过 admin_menu 钩子与 add_submenu_page,在 Books 菜单下添加子页面:
add_action( 'admin_menu', 'bookstore_add_booklist_submenu', 11 );
function bookstore_add_booklist_submenu() {
add_submenu_page(
'edit.php?post_type=book',
'Book List',
'Book List',
'edit_posts',
'book-list',
'bookstore_render_booklist'
);
}
再创建渲染页面 HTML 的回调:
function bookstore_render_booklist() {
?>
<div class="wrap" id="bookstore-booklist-admin">
<h1>Actions</h1>
<button id="bookstore-load-books">Load Books</button>
<h2>Books</h2>
<textarea id="bookstore-booklist" cols="125" rows="15"></textarea>
</div>
<?php
}
后台 Books 菜单现在出现“Book List”,打开可看到“Load Books”按钮与文本框。
可以用 PHP 获取列表,并让按钮触发刷新。但为了更流畅的体验,下面使用 JavaScript 与 REST API 异步获取数据,无需刷新整页。
加载后台 JavaScript
插件入门模块介绍过脚本加载。由于功能位于后台,需要单独调用 wp_enqueue_script,并挂到 admin_enqueue_scripts,确保脚本只在后台加载。
在插件目录创建 admin_bookstore.js,再向主文件添加:
add_action( 'admin_enqueue_scripts', 'bookstore_admin_enqueue_scripts' );
function bookstore_admin_enqueue_scripts() {
wp_enqueue_script(
'bookstore-admin',
plugins_url() . '/bookstore/admin_bookstore.js',
array(),
'1.0.0',
true
);
}
代码指定了空依赖数组、版本号,并把最后一个参数设为 true,让脚本在页脚加载。参数详情见 wp_enqueue_script 参考。
可暂时添加下面的 alert,刷新后台确认脚本已加载,之后删除这行:
alert( 'Hello from the Book store admin' );
方式一:Backbone.js 客户端
REST API 加入 WordPress 时,就包含了基于 Backbone.js 的 JavaScript 客户端,为所有暴露的端点提供 Model 与 Collection。
要使用它,将 wp-api 加入脚本依赖,即 wp_enqueue_script 的第三个参数:
wp_enqueue_script(
'bookstyle-script',
plugins_url() . '/bookstore/admin_bookstore.js',
array( 'wp-api' ),
'1.0.0',
true
);
这样插件脚本只会在 REST 客户端加载后运行。
先给按钮注册点击事件:
const loadBooksByRestButton = document.getElementById( 'bookstore-load-books' );
if ( loadBooksByRestButton ) {
loadBooksByRestButton.addEventListener( 'click', function () {
//do somthing
} );
}
在回调中,通过全局 wp 对象创建图书集合:
const allBooks = new wp.api.collections.Books();
此时集合为空,需要调用 fetch:
allBooks.fetch();
fetch 返回 Promise,可以链式调用 done 处理响应,并用 books 参数接收结果:
allBooks.fetch().done(
function ( books ) {
// do something with books
}
);
然后使用 forEach 遍历每本书:
allBooks.fetch().done(
function ( books ) {
books.forEach( function ( book ) {
// do something with book
} );
}
);
最后把标题和永久链接加入文本框。先在循环外取得文本框,再在循环内追加到 value:
allBooks.fetch().done(
function ( books ) {
const textarea = document.getElementById( 'bookstore-booklist' );
books.forEach( function ( book ) {
textarea.value += book.title.rendered + ',' + book.link + ',\n'
});
}
);
完整代码如下:
const loadBooksByRestButton = document.getElementById( 'bookstore-load-books' );
if ( loadBooksByRestButton ) {
loadBooksByRestButton.addEventListener( 'click', function () {
const allBooks = new wp.api.collections.Books();
allBooks.fetch().done(
function ( books ) {
const textarea = document.getElementById( 'bookstore-booklist' );
books.forEach( function ( book ) {
textarea.value += book.title.rendered + ',' + book.link + ',\n'
});
}
);
});
}
回到 Book List,点击“Load Books”,文本框会显示图书列表。
方式二:apiFetch
WordPress 5.0 引入区块编辑器后,也提供了 API Fetch 包,封装浏览器 fetch API,以更现代、灵活的方式请求 REST API。原文小节称其为 @wordpress/fetch-api,后面的参考链接为 api-fetch 包。
将 wp-api-fetch 加入插件脚本依赖:
wp_enqueue_script(
'bookstyle-script',
plugins_url() . '/bookstore/admin_bookstore.js',
array( 'wp-api', 'wp-api-fetch' ),
'1.0.0',
true
);
可以移除原来的 wp-api,也可以同时保留。
在 Actions 区域添加按钮:
<button id="bookstore-fetch-books">Fetch Books</button>
与前面一样,为新按钮添加 click 监听器,这次使用 apiFetch:
const fetchBooksByRestButton = document.getElementById( 'bookstore-fetch-books' );
if ( fetchBooksByRestButton ) {
fetchBooksByRestButton.addEventListener( 'click', function () {
wp.apiFetch( { path: '/wp/v2/books' } ).then( ( books ) => {
const textarea = document.getElementById( 'bookstore-booklist' );
books.map( ( book ) => {
textarea.value += book.title.rendered + ',' + book.link + ',\n'
});
} );
});
}
端点路径通过对象传给 wp.apiFetch,比必须使用特定 Collection 的 Backbone 客户端更灵活。
then 与前面的 done 类似,等待请求完成,再将结果传给回调。回调中用 map 遍历 books,将标题与链接追加到文本框。这段代码采用更现代的箭头函数语法。
刷新后台,点击“Fetch Books”,即可看到列表。
方式三:@wordpress/core-data
开发区块时,也可以使用 core-data 访问 REST 数据。它简化 WordPress 核心实体的读取和修改,注册自己的 store,提供自动解析 REST 数据的 selector,以及用于修改数据的 action creator。
core-data 使用 React 功能,因此最适合区块环境。
先使用区块开发入门中介绍的 create-block,创建 bookstore-block:
cd path/to/local/site/wp-content/plugins
npx @wordpress/create-block bookstore-block
脚手架会生成可编辑代码。在 edit.js 中导入 useSelect 和 core-data store:
import { useSelect } from '@wordpress/data';
import { store as bookStore } from '@wordpress/core-data';
然后读取图书:
const books = useSelect(
select =>
select( bookStore ).getEntityRecords( 'postType', 'book' ),
[]
);
useSelect 从已注册 selector 中取数据。第一个参数是回调,在其中调用 bookStore 的 getEntityRecords,结果保存到 books。
没有数据时返回空组件,否则遍历图书并输出标题、链接:
if ( ! books ) {
return (
<div { ...useBlockProps() }></div>
)
}
return (
<div { ...useBlockProps() }>
{ books.map( ( book ) => (
<p>
<a href={ book.link }>{book.title.rendered}</a>
</p>
) ) }
</div>
);
运行区块构建,启用插件,并把 bookstore 区块加入文章或页面,就能看到从 REST API 获取的标题和链接。
三种方式的区别
Backbone 客户端最早出现,与 REST API 集成紧密。需要用 REST API 构建后台页面时,是不错的选择,也比旧 admin-ajax.php 端点更合适。
apiFetch 是通用方案,既适用于后台页面,也适用于编辑器区块;更现代,也比 Backbone 更灵活。
core-data 最适合区块,因为它依赖区块编辑器环境中的 React 功能。
进一步阅读
更多信息见 REST API 手册的 Backbone JavaScript 客户端部分,以及区块编辑器手册的 api-fetch 和 core-data 包。
原文:Using the WordPress REST API。作者/维护者:WordPress Learn 教学团队。本文为原文的中文译文;代码保留原文内容。











暂无评论内容