概述
REST API 为我们提供了一种将 URI 映射到 WordPress 安装中各种资源的方法。默认情况下,如果您启用了友好链接(pretty permalinks),WordPress REST API 位于 /wp-json/。在我们的 WordPress 站点 https://ourawesomesite.com 上,我们可以通过向 https://ourawesomesite.com/wp-json/ 发送一个 GET 请求来访问 REST API 的索引。该索引提供了关于该特定 WordPress 安装可用的路由、支持的 HTTP 方法以及已注册的端点的信息。
路由与端点
端点是可通过 API 调用的函数。这包括检索 API 索引、更新帖子或删除评论等操作。端点执行特定功能,接收一定数量的参数并向客户端返回数据。
路由是您用于通过 URL 访问端点的“名称”。一个路由可以关联多个端点,具体使用哪一个取决于 HTTP 动词。
例如,对于 URL `http://example.com/wp-json/wp/v2/posts/123`:
- “路由”是
wp/v2/posts/123– 路由不包含wp-json,因为wp-json是 API 本身的基础路径。 - 此路由有 3 个端点:
GET触发get_item方法,向客户端返回帖子数据。PUT触发update_item方法,接收要更新的数据,并返回更新后的帖子数据。DELETE触发delete_item方法,向客户端返回已被删除的帖子数据。
在未启用友好链接的站点上,路由会作为 rest_route 参数添加到 URL 中。对于上述示例,完整的 URL 将是 http://example.com/?rest_route=/wp/v2/posts/123
创建端点
如果我们想创建一个端点,使其在接收到 GET 请求时返回短语"Hello World, this is the WordPress REST API",我们首先需要为该端点注册路由。注册路由应使用 register_rest_route() 函数。它必须在 rest_api_init 动作钩子上被调用。register_rest_route() 处理所有路由到端点的映射。让我们尝试创建一个"Hello World, this is the WordPress REST API"路由。
/**
* This is our callback function that embeds our phrase in a WP_REST_Response
*/
function prefix_get_endpoint_phrase() {
// rest_ensure_response() wraps the data we want to return into a WP_REST_Response, and ensures it will be properly returned.
return rest_ensure_response( 'Hello World, this is the WordPress REST API' );
}
/**
* This function is where we register our routes for our example endpoint.
*/
function prefix_register_example_routes() {
// register_rest_route() handles more arguments but we are going to stick to the basics for now.
register_rest_route( 'hello-world/v1', '/phrase', array(
// By using this constant we ensure that when the WP_REST_Server changes our readable endpoints will work as intended.
'methods' => WP_REST_Server::READABLE,
// Here we register our callback. The callback is fired when this endpoint is matched by the WP_REST_Server class.
'callback' => 'prefix_get_endpoint_phrase',
) );
}
add_action( 'rest_api_init', 'prefix_register_example_routes' );
传递给 register_rest_route() 的第一个参数是命名空间,它为我们提供了一种分组路由的方法。传入的第二个参数是资源路径或资源基础。在我们的示例中,我们要检索的资源是"Hello World, this is the WordPress REST API"短语。第三个参数是一组选项数组。我们指定端点可以使用哪些方法,以及在匹配该端点时应调用哪个回调函数(虽然还可以做更多事情,但这些都是基础)。
第三个参数还允许我们提供一个权限回调函数,从而将端点的访问权限限制为仅限某些用户。第三个参数还提供了一种为端点注册参数的方法,以便请求可以修改端点的响应。我们将在本指南的端点部分深入探讨这些概念。
当我们访问 https://ourawesomesite.com/wp-json/hello-world/v1/phrase 时,现在可以看到我们的 REST API 友好地向我们打招呼了。让我们更深入地了解一下路由。
路由
REST API 中的路由由 URI 表示。路由本身是附加在 https://ourawesomesite.com/wp-json 末尾的部分。API 的索引路由是 /,这就是为什么 https://ourawesomesite.com/wp-json/ 返回 API 的所有可用信息的原因。所有路由都应构建在此路由之上,wp-json 部分可以更改,但通常建议保持原样。
我们要确保路由是唯一的。例如,我们可以有一个像这样的书籍路由:/books。我们的书籍路由将位于 https://ourawesomesite.com/wp-json/books。然而,这不是一个好做法,因为我们最终会污染 API 的潜在路由。如果我们想让另一个插件也注册一个书籍路由怎么办?在那种情况下我们会遇到大麻烦,因为两个路由会相互冲突,只能使用其中一个。第四个参数 register_rest_route() 是一个布尔值,用于指示路由是否应覆盖现有路由。
覆盖参数并不能真正解决我们的问题,因为两个路由都可能互相覆盖,或者我们希望为不同的用途同时使用这两个路由。这正是我们需要为路由使用命名空间的地方。
命名空间
为您的路由添加命名空间极其重要。“核心”端点使用 wp/v2 命名空间。
wp 命名空间。在核心端点命名空间中有一些关键点需要注意。命名空间的第一部分是 wp,代表供应商名称:WordPress。对于我们的插件,我们需要为命名空间的供应商部分想出唯一的名称。在上述示例中,我们使用了 hello-world。
紧随供应商部分之后的是命名空间的版本部分。“核心”端点使用 v2 来表示 WordPress REST API 的第 2 版。如果您正在编写插件,可以通过简单地创建新端点并提高所提供的版本号来维护 REST API 端点的向后兼容性。这样,原始的 v1 和 v2 端点都可以被访问。
路由中紧跟命名空间之后的部分是资源路径。
资源路径
资源路径应表明该端点关联的是什么资源。在我们上面使用的示例中,我们使用了单词 phrase 来表示我们正在交互的资源是一个短语。为了避免任何冲突,我们在每个命名空间中注册的每个资源路径也应该是唯一的。资源路径应用于定义给定命名空间内的不同资源路由。
假设我们有一个处理基本电子商务功能的插件。我们将有两个主要的资源类型:订单(orders)和产品(products)。订单是对产品的请求,但它们本身不是产品。同样的概念适用于产品。尽管这些资源相关,但它们不是同一件事,每个都应该位于单独的资源路径中。我们的路由最终对于我们的电子商务插件看起来会像这样:/my-shop/v1/orders 和 /my-shop/v1/products。
使用这样的路由,我们希望每个路由返回订单或产品的集合。如果我们想通过 ID 获取特定的产品怎么办?我们需要在路由中使用路径变量。
路径变量
路径变量使我们能够添加动态路由。为了扩展我们的电子商务路由,我们可以注册一个路由来获取单个产品。
/**
* 这是我们的回调函数,用于返回我们的产品。
*
* @param WP_REST_Request $request 此函数接受一个 REST 请求以处理数据。
*/
function prefix_get_products( $request ) {
// 在实际应用中,此函数会获取所需的数据。这里我们只是随意编造了一些数据。
$products = array(
'1' => '我是产品 1',
'2' => '我是产品 2',
'3' => '我是产品 3',
);
return rest_ensure_response( $products );
}
/**
* 这是我们的回调函数,用于返回单个产品。
*
* @param WP_REST_Request $request 此函数接受一个 REST 请求以处理数据。
*/
function prefix_get_product( $request ) {
// 在实际应用中,此函数会获取所需的数据。这里我们只是随意编造了一些数据。
$products = array(
'1' => '我是产品 1',
'2' => '我是产品 2',
'3' => '我是产品 3',
);
// 在这里,我们从 $request 对象中获取 'id' 路径变量。WP_REST_Request 实现了 ArrayAccess,这允许我们像访问数组属性一样获取属性。
$id = (string) $request['id'];
if ( isset( $products[ $id ] ) ) {
// 获取该产品。
$product = $products[ $id ];
// 将产品作为响应返回。
return rest_ensure_response( $product );
} else {
// 返回一个 WP_Error,因为请求的产品未找到。在这种情况下,我们返回 404,因为主资源未找到。
return new WP_Error( 'rest_product_invalid', esc_html__( '该产品不存在。', 'my-text-domain' ), array( 'status' => 404 ) );
}
// 如果代码意外执行到这里,说明发生了严重错误,返回 500。
return new WP_Error( 'rest_api_sad', esc_html__( '发生严重错误。', 'my-text-domain' ), array( 'status' => 500 ) );
}
/**
* 此函数是我们注册示例端点路由的地方。
*/
function prefix_register_product_routes() {
// 在这里,我们注册产品集合的路由。
register_rest_route( 'my-shop/v1', '/products', array(
// 使用此常量可确保当 WP_REST_Server 更改时,我们的可读端点能按预期工作。
'methods' => WP_REST_Server::READABLE,
// 在这里注册我们的回调。当 WP_REST_Server 类匹配此端点时,将触发回调。
'callback' => 'prefix_get_products',
) );
// 在这里,我们注册单个产品的路由。(?P<id>[\d]+) 是我们的 ID 路径变量,在本例中,它只能是某种形式的正数。
register_rest_route( 'my-shop/v1', '/products/(?P<id>[\d]+)', array(
// 使用此常量可确保当 WP_REST_Server 更改时,我们的可读端点能按预期工作。
'methods' => WP_REST_Server::READABLE,
// 在这里注册我们的回调。当 WP_REST_Server 类匹配此端点时,将触发回调。
'callback' => 'prefix_get_product',
) );
}
add_action( 'rest_api_init', 'prefix_register_product_routes' );
上述示例涵盖了很多内容。需要注意的重要部分是,在我们注册的第二个路由中,我们在资源路径 /products 上添加了一个路径变量 /(?P<id>[\d]+)。路径变量是一个正则表达式。在此情况下,它使用 [\d]+ 来表示应至少出现一次任何数字字符。如果您为资源使用数字 ID,那么这是一个如何正确使用路径变量的绝佳示例。在使用路径变量时,我们现在必须小心对待可能匹配的内容,因为它是用户输入。
幸运的是,正则表达式会过滤掉任何非数字内容。但是,如果请求 ID 对应的产品不存在怎么办?我们需要进行错误处理。您可以在上面的代码示例中看到我们处理错误的基本方式。当您在端点回调中返回 WP_Error 时,API 服务器将自动处理向客户端提供错误。
虽然本节是关于路由的,但我们已经涵盖了相当多的关于端点的内容。端点和路由是相互关联的,但它们确实有区别。
端点
端点是路由需要映射到的目标。对于任何给定的路由,您可以注册多个不同的端点。我们将扩展虚构的电子商务插件,以更好地展示路由和端点之间的区别。我们将在 /wp-json/my-shop/v1/products/ 路由处创建两个端点。一个端点使用 HTTP 动词 GET 来获取产品,另一个端点使用 HTTP 动词 POST 来创建新产品。
/**
* 这是我们的回调函数,用于返回我们的产品。
*
* @param WP_REST_Request $request 此函数接受一个 REST 请求以处理数据。
*/
function prefix_get_products( $request ) {
// 在实际应用中,此函数会获取所需的数据。这里我们只是随意编造了一些数据。
$products = array(
'1' => '我是产品 1',
'2' => '我是产品 2',
'3' => '我是产品 3',
);
return rest_ensure_response( $products );
}
/**
* 这是我们的回调函数,用于返回单个产品。
*
* @param WP_REST_Request $request 此函数接受一个 REST 请求以处理数据。
*/
function prefix_create_product( $request ) {
// 在实际应用中,此函数会创建一个产品。这里我们只是随意编造了一些数据。
return rest_ensure_response( 'Product has been created' );
}
/**
* 此函数是我们注册示例端点路由的地方。
*/
function prefix_register_product_routes() {
// 在这里,我们注册产品集合的路由以及创建产品的路由。
register_rest_route( 'my-shop/v1', '/products', array(
array(
// 使用此常量可确保当 WP_REST_Server 更改时,我们的可读端点能按预期工作。
'methods' => WP_REST_Server::READABLE,
// 在这里注册我们的回调。当 WP_REST_Server 类匹配此端点时,将触发回调。
'callback' => 'prefix_get_products',
),
array(
// 使用此常量可确保当 WP_REST_Server 更改时,我们的创建端点能按预期工作。
'methods' => WP_REST_Server::CREATABLE,
// 在这里注册我们的回调。当 WP_REST_Server 类匹配此端点时,将触发回调。
'callback' => 'prefix_create_product',
),
) );
}
add_action( 'rest_api_init', 'prefix_register_product_routes' );
根据我们对路由 /wp-json/my-shop/v1/products 使用的 HTTP 方法,我们将匹配到不同的端点,并触发不同的回调。当我们使用 POST 时,会触发 prefix_create_product() 回调,而当我们使用 GET 时,会触发 prefix_get_products() 回调。
有多种不同的 HTTP 方法,REST API 可以使用其中任何一种。
HTTP 方法
HTTP 方法有时也称为 HTTP 动词。它们仅仅是通过 HTTP 进行通信的不同方式。WordPress REST API 主要使用的是:
GET应用于从 API 检索数据。POST应用于创建新资源(即用户、文章、分类法)。PUT应用于更新资源。DELETE应用于删除资源。OPTIONS应用于提供有关我们资源的上下文信息。
需要注意的是,并非所有客户端都支持这些方法,因为它们是在 HTTP 1.1 中引入的。幸运的是,API 为此类不幸情况提供了变通方案。如果您想删除资源但无法发送 DELETE 请求,则可以在请求中使用 _method 参数或 X-HTTP-Method-Override 标头。工作原理是:您将发送一个 POST 请求到 `https://ourawesomesite.com/wp-json/my-shop/v1/products/1?_method=DELETE`。现在,即使您的客户端无法在请求中发送正确的 HTTP 方法,或者可能有防火墙阻止了 DELETE 请求,您也已经删除了编号为 1 的产品。
HTTP 方法结合路由和回调,构成了端点的核心。
回调
目前,REST API 仅支持两种类型的端点回调:callback 和 permission_callback。主回调应处理与资源的交互。权限回调应处理哪些用户可以访问该端点。您可以通过在注册端点时添加额外信息来添加额外的回调。然后,您可以挂钩 rest_pre_dispatch、rest_dispatch_request 或 rest_post_dispatch 钩子来触发您新的自定义回调。
端点回调
删除端点的主回调应仅删除资源并在响应中返回其副本。创建端点的主回调应仅创建资源并返回与新创建数据匹配的响应。更新回调应仅修改实际存在的资源。读取回调应仅检索已存在的数据。重要的是要考虑幂等性的概念。
幂等性在 REST API 的上下文中意味着,如果您向某个端点发送相同的请求,服务器将以相同的方式处理该请求。试想一下,如果我们的读取端点不是幂等的。每当我们向其发送请求时,服务器的状态都会被修改,即使我们只是试图获取数据。这将是灾难性的。每次有人从您的服务器获取数据时,内部都会发生某种变化。重要的是要确保读取、更新和删除端点不会产生有害的副作用,并且仅执行其预期的操作。
在 REST API 中,幂等性与 HTTP 方法相关联,而不是端点回调。任何使用 GET、HEAD、TRACE、OPTIONS、PUT 或 DELETE 的回调都不应产生任何副作用。POST 请求不是幂等的,通常用于创建资源。如果您创建一个幂等的创建方法,那么您将只能创建一个资源,因为当您发出相同的请求时,服务器将不再有任何副作用。对于创建操作,如果您反复发出相同的请求,服务器应该每次都生成新资源。
为了限制端点的使用,我们需要注册一个权限回调函数。
权限回调函数
权限回调函数对于 WordPress REST API 的安全性至关重要。如果您有任何不应公开显示的私有数据,那么您需要为您的端点注册权限回调函数。下面是一个如何注册权限回调函数的示例。
/**
* 这是我们的回调函数,它将我们的资源嵌入到 WP_REST_Response 中
*/
function prefix_get_private_data() {
// rest_ensure_response() 将我们要返回的数据包装成 WP_REST_Response,并确保其能正确返回。
return rest_ensure_response( 'This is private data.' );
}
/**
* 这是我们的回调函数,它将我们的资源嵌入到 WP_REST_Response 中
*/
function prefix_get_private_data_permissions_check() {
// 限制端点仅限具有 edit_posts 能力的用户访问。
if ( ! current_user_can( 'edit_posts' ) ) {
return new WP_Error( 'rest_forbidden', esc_html__( 'OMG you can not view private data.', 'my-text-domain' ), array( 'status' => 401 ) );
}
// 这是一种黑名单方法。您也可以通过白名单方式实现,即在此处返回 false 并更改权限检查。
return true;
}
/**
* 这是我们要为示例端点注册路由的函数。
*/
function prefix_register_example_routes() {
// register_rest_route() 处理更多参数,但我们现在将坚持使用基础用法。
register_rest_route( 'my-plugin/v1', '/private-data', array(
// 通过使用此常量,我们确保当 WP_REST_Server 发生变化时,我们的可读端点仍能按预期工作。
'methods' => WP_REST_Server::READABLE,
// 在这里我们注册我们的回调函数。当 WP_REST_Server 类匹配此端点时,将触发此回调函数。
'callback' => 'prefix_get_private_data',
// 在这里我们注册我们的权限回调函数。在主回调函数之前触发此回调函数,以检查当前用户是否可以访问该端点。
'permission_callback' => 'prefix_get_private_data_permissions_check',
) );
}
add_action( 'rest_api_init', 'prefix_register_example_routes' );
如果您在不启用任何身份验证的情况下尝试此端点,您也将收到错误响应,从而阻止您查看数据。身份验证是一个巨大的话题,最终本章将有一部分内容向您展示如何创建自己的身份验证流程。
参数
在向端点发送请求时,您可能需要指定额外参数来更改响应。这些额外参数可以在注册端点时添加。让我们看看如何在端点中使用参数的示例。
/**
* 这是我们的回调函数,它将我们的资源嵌入到 WP_REST_Response 中
*/
function prefix_get_colors( $request ) {
// 在实际应用中,此函数将获取所需数据。这里我们只是编造一些数据。
$colors = array(
'blue',
'blue',
'red',
'red',
'green',
'green',
);
if ( isset( $request['filter'] ) ) {
$filtered_colors = array();
foreach ( $colors as $color ) {
if ( $request['filter'] === $color ) {
$filtered_colors[] = $color;
}
}
return rest_ensure_response( $filtered_colors );
}
return rest_ensure_response( $colors );
}
/**
* 我们可以使用此函数来包含示例产品端点的参数。
*/
function prefix_get_color_arguments() {
$args = array();
// 在这里我们为 filter 参数注册模式。
$args['filter'] = array(
// description 应该是人类可读的参数描述。
'description' => esc_html__( 'The filter parameter is used to filter the collection of colors', 'my-text-domain' ),
// type 指定参数应为哪种数据类型。
'type' => 'string',
// enum 指定 filter 可以采用的值。
'enum' => array( 'red', 'green', 'blue' ),
);
return $args;
}
/**
* 这是我们要为示例端点注册路由的函数。
*/
function prefix_register_example_routes() {
// register_rest_route() 处理更多参数,但我们现在将坚持使用基础用法。
register_rest_route( 'my-colors/v1', '/colors', array(
// 通过使用此常量,我们确保当 WP_REST_Server 发生变化时,我们的可读端点仍能按预期工作。
'methods' => WP_REST_Server::READABLE,
// 在这里我们注册我们的回调函数。当 WP_REST_Server 类匹配此端点时,将触发此回调函数。
'callback' => 'prefix_get_colors',
// 在这里我们注册我们的权限回调函数。在主回调函数之前触发此回调函数,以检查当前用户是否可以访问该端点。
'args' => prefix_get_color_arguments(),
) );
}
add_action( 'rest_api_init', 'prefix_register_example_routes' );
我们现在已为此示例指定了一个 filter 参数。我们在请求端点时可以将其指定为查询参数。如果我们向 `https://ourawesomesitem.com/my-colors/v1/colors?filter=blue` 发起 GET 请求,我们将只收到集合中的蓝色颜色。您也可以将这些作为请求体中的主体参数传递,而不是在查询字符串中。要了解查询参数和主体参数之间的区别,您应该阅读 HTTP 规范。查询参数位于附加在 URL 末尾的查询字符串中,而主体参数直接嵌入在 HTTP 请求的主体中。
我们已经为我们的端点创建了一个参数,但如何验证该参数是字符串类型,并判断它是否匹配 red、green 或 blue 的值呢?要做到这一点,我们需要为我们的参数指定一个验证回调函数。
验证
验证和清理对于 API 的安全性至关重要。验证回调函数(在 WP 4.6+ 版本中)在清理回调函数之前触发。您应该使用 validate_callback 来验证您接收到的输入是否有效。sanitize_callback 应用于在处理主回调函数之前转换参数输入或清除参数中不需要的部分。
在上述示例中,我们需要验证 filter 参数是否为字符串,并且它是否匹配 red、green 或 blue 的值。让我们看看在添加了 validate_callback 之后的代码是什么样子的。
/**
* 这是我们的回调函数,用于将资源嵌入到 WP_REST_Response 中。
*/
function prefix_get_colors( $request ) {
// 在实践中,此函数会获取更实际的数据。这里我们只是随意构造数据。
$colors = array(
'blue',
'blue',
'red',
'red',
'green',
'green',
);
if ( isset( $request['filter'] ) ) {
$filtered_colors = array();
foreach ( $colors as $color ) {
if ( $request['filter'] === $color ) {
$filtered_colors[] = $color;
}
}
return rest_ensure_response( $filtered_colors );
}
return rest_ensure_response( $colors );
}
/**
* 根据注册到路由的详细信息验证请求参数。
*
* @param mixed $value 'filter' 参数的值。
* @param WP_REST_Request $request 当前请求对象。
* @param string $param 参数的键。在本例中为 'filter'。
* @return WP_Error|boolean
*/
function prefix_filter_arg_validate_callback( $value, $request, $param ) {
// 如果 'filter' 参数不是字符串,则返回错误。
if ( ! is_string( $value ) ) {
return new WP_Error( 'rest_invalid_param', esc_html__( '过滤参数必须是字符串。', 'my-text-domain' ), array( 'status' => 400 ) );
}
// 获取此端点请求注册的属性。
$attributes = $request->get_attributes();
// 获取 filter 参数的架构。
$args = $attributes['args'][ $param ];
// 如果 filter 参数不是我们枚举中的值,我们也应返回错误。
if ( ! in_array( $value, $args['enum'], true ) ) {
return new WP_Error( 'rest_invalid_param', sprintf( __( '%s 不是 %s 之一' ), $param, implode( ', ', $args['enum'] ) ), array( 'status' => 400 ) );
}
}
/**
* 我们可以使用此函数来包含示例产品端点的参数。
*/
function prefix_get_color_arguments() {
$args = array();
// 在这里我们为 filter 参数注册架构。
$args['filter'] = array(
// description 应该是参数的可读描述。
'description' => esc_html__( '过滤参数用于过滤颜色集合。', 'my-text-domain' ),
// type 指定参数应为哪种数据类型。
'type' => 'string',
// enum 指定 filter 可以取的值。
'enum' => array( 'red', 'green', 'blue' ),
// 在这里我们为 filter 参数注册验证回调。
'validate_callback' => 'prefix_filter_arg_validate_callback',
);
return $args;
}
/**
* 这是我们在其中注册示例端点路由的函数。
*/
function prefix_register_example_routes() {
// register_rest_route() 处理更多参数,但我们现在将坚持使用基础用法。
register_rest_route( 'my-colors/v1', '/colors', array(
// 通过使用此常量,我们确保当 WP_REST_Server 更改时,我们的可读端点仍能按预期工作。
'methods' => WP_REST_Server::READABLE,
// 在这里我们注册回调。当 WP_REST_Server 类匹配此端点时,将触发该回调。
'callback' => 'prefix_get_colors',
// 在这里我们注册权限回调。在主回调之前触发此回调,以检查当前用户是否可以访问该端点。
'args' => prefix_get_color_arguments(),
) );
}
add_action( 'rest_api_init', 'prefix_register_example_routes' );
清理(Sanitizing)
在上面的示例中,我们不需要使用 sanitize_callback,因为我们已将输入限制为我们枚举中的值。如果我们没有严格的验证并接受任何字符串作为参数,那么我们肯定需要注册一个 sanitize_callback。如果我们想更新内容字段,而用户输入了类似 alert('ZOMG Hacking you'); 的内容怎么办?字段值可能会成为可执行的脚本。为了移除不需要的数据或将数据转换为所需格式,我们需要为参数注册一个 sanitize_callback。以下是如何使用 WordPress 的 sanitize_text_field() 作为清理回调的示例:
/**
* 这是我们的回调函数,用于将资源嵌入到 WP_REST_Response 中。
*
* 在此阶段参数已经过清理,因此我们可以放心地使用它。
*/
function prefix_get_item( $request ) {
if ( isset( $request['data'] ) ) {
return rest_ensure_response( $request['data'] );
}
return new WP_Error( 'rest_invalid', esc_html__( '数据参数是必需的。', 'my-text-domain' ), array( 'status' => 400 ) );
}
/**
* 根据注册到路由的详细信息验证请求参数。
*
* @param mixed $value 'filter' 参数的值。
* @param WP_REST_Request $request 当前请求对象。
* @param string $param 参数的键。在本例中为 'filter'。
* @return WP_Error|boolean
*/
function prefix_data_arg_validate_callback( $value, $request, $param ) {
// 如果 'data' 参数不是字符串,则返回错误。
if ( ! is_string( $value ) ) {
return new WP_Error( 'rest_invalid_param', esc_html__( '过滤参数必须是字符串。', 'my-text-domain' ), array( 'status' => 400 ) );
}
}
/**
* 根据注册到路由的详细信息清理请求参数。
*
* @param mixed $value 'filter' 参数的值。
* @param WP_REST_Request $request 当前请求对象。
* @param string $param 参数的键。在本例中为 'filter'。
* @return WP_Error|boolean
*/
function prefix_data_arg_sanitize_callback( $value, $request, $param ) {
// 只需返回清理后的值即可。
return sanitize_text_field( $value );
}
/**
* 我们可以使用此函数来包含示例产品端点的参数。
*/
function prefix_get_data_arguments() {
$args = array();
// 在这里我们为 filter 参数注册架构。
$args['data'] = array(
// description 应该是参数的可读描述。
'description' => esc_html__( '数据参数用于被清理并在响应中返回。', 'my-text-domain' ),
// type 指定参数应为哪种数据类型。
'type' => 'string',
// 设置该参数为端点必需。
'required' => true,
// 我们为 data 参数注册基本验证回调。
'validate_callback' => 'prefix_data_arg_validate_callback',
// 在这里我们为 filter 参数注册清理回调。
'sanitize_callback' => 'prefix_data_arg_sanitize_callback',
);
return $args;
}
/**
* 这是我们在其中注册示例端点路由的函数。
*/
function prefix_register_example_routes() {
// register_rest_route() 处理更多参数,但我们现在将坚持使用基础用法。
register_rest_route( 'my-plugin/v1', '/sanitized-data', array(
// 通过使用此常量,我们确保当 WP_REST_Server 更改时,我们的可读端点仍能按预期工作。
'methods' => WP_REST_Server::READABLE,
// 在这里我们注册回调。当 WP_REST_Server 类匹配此端点时,将触发该回调。
'callback' => 'prefix_get_item',
// 在这里我们注册权限回调。在主回调之前触发此回调,以检查当前用户是否可以访问该端点。
'args' => prefix_get_data_arguments(),
) );
}
add_action( 'rest_api_init', 'prefix_register_example_routes' );
总结
我们已经介绍了为 WordPress REST API 注册端点的基础知识。路由(Routes)是我们端点所在的 URI。端点是一组回调、方法、参数和其他选项。在使用 register_rest_route() 时,每个端点都映射到一个路由。默认情况下,端点可以支持各种 HTTP 方法、主回调、权限回调和已注册的参数。我们可以注册端点以覆盖我们与 WordPress 交互的任何用例。端点是与 REST API 进行核心交互的点,但还有众多其他主题需要探索和了解,以便充分利用这个强大的 API。