WordPress中文开发手册

路由和端点

REST API为我们提供了一种将URI匹配到我们的WordPress安装中的各种资源的方法。 默认情况下,如果您启用了漂亮的永久链接,则WordPress REST API“生活在/ wp-json /”。 在我们的WordPress网站https://ourawesomesite.com上,我们可以通过向https://ourawesomesite.com/wp-json/发出GET请求来访问REST API的索引。 该索引提供有关可用于特定WordPress安装的路由的信息,以及支持哪些HTTP方法以及注册了哪些端点。

路线与端点

端点是通过API可用的功能。这可以是检索API索引,更新帖子或删除注释。端点执行一个特定的功能,采取一些参数和返回数据到客户端。

路由是您用于访问端点的“名称”,用于URL中。一个路由可以有多个端点与它相关联,哪个使用取决于HTTP动词。

例如,使用网址http://example.com/wp-json/wp/v2/posts/123:

“route”是wp / v2 / posts / 123 - 路由不包括wp-json,因为wp-json是API本身的基本路径。

该路由有3个端点:

  • GET触发一个get_item方法,将post数据返回给客户端。
  • PUT触发update_item方法,使数据更新,并返回更新后的数据。
  • DELETE触发一个delete_item方法,将现在删除的帖子数据返回给客户端。

警报:在没有很好的固定链接的站点上,路由替代地添加到URL作为rest_route参数。对于上述示例,完整的网址将是http://example.com/?rest_route=/wp/v2/posts/123

创建端点

如果我们想要创建一个返回短语“Hello World”的端点,当它接收到一个GET请求时,我们首先需要注册该端点的路由。 要注册路由,您应该使用register_rest_route()函数。 它需要在rest_api_init操作钩子上调用。 register_rest_route()处理到端点的路由的所有映射。 我们尝试创建一个“Hello World,这是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,这是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_field()的第四个参数是一个布尔值,用于路由是否应该覆盖现有路由。

覆盖参数也不能真正解决我们的问题,因为两个路由都可以覆盖,或者我们想要使用两个路由来做不同的事情。这是我们的路线使用命名空间的地方。

##命名空间

添加命名空间到您的路由是非常重要的。 “核心”端点使用wp / v2命名空间。

警告:不要将任何东西放入wp命名空间中,除非您正在将端点合并成核心。

在核心端点命名空间中有一些关键的事情要注意。命名空间的第一部分是wp,它代表供应商名称; WordPress。对于我们的插件,我们将想要提供我们称为命名空间的供应商部分的唯一名称。在上面的例子中,我们使用了hello-world。

跟随供应商部分是命名空间的版本部分。 “核心”端点使用v2来表示WordPress REST API的版本2。如果您正在编写一个插件,您可以通过简单地创建新的端点并增加您提供的版本号来保持REST API端点的向后兼容性。这样可以访问原始v1和v2端点。

命名空间后面的路由部分是资源路径。

资源路径

资源路径应该表示端点与哪个资源相关联。在上面我们使用的例子中,我们使用单词来表示我们正在交互的资源是一个短语。为了避免任何冲突,我们注册的每个资源路径在命名空间中也应该是唯一的。资源路径应用于定义给定命名空间内的不同资源路由。

假设我们有一个插件来处理一些基本的电子商务功能。我们将有两种主要的资源类型订单和产品。订单是对产品的请求,但它们不是产品本身。同样的概念适用于产品。虽然这些资源是相关的,但它们并不一样,每个资源都应该存在于单独的资源路径中。我们的路线最终会看到我们的电子商务插件:/ my-shop / v1 / orders和/ my-shop / v1 / products。

使用这样的路线,我们希望每个都返回一个订单或产品的集合。如果我们想通过ID获取特定的产品,我们需要在路由中使用路径变量。

路径变量

路径变量使我们能够添加动态路由。为了扩展我们的电子商务路线,我们可以注册一条路线来抢购个别产品。

/**
 * This is our callback function to return our products.
 *
 * @param WP_REST_Request $request This function accepts a rest request to process data.
 */
function prefix_get_products( $request ) {
    // In practice this function would fetch the desired data. Here we are just making stuff up.
    $products = array(
        '1' => 'I am product 1',
        '2' => 'I am product 2',
        '3' => 'I am product 3',
    );
     
    return rest_ensure_response( $products );
}
 
/**
 * This is our callback function to return a single product.
 *
 * @param WP_REST_Request $request This function accepts a rest request to process data.
 */
function prefix_get_product( $request ) {
    // In practice this function would fetch the desired data. Here we are just making stuff up.
    $products = array(
        '1' => 'I am product 1',
        '2' => 'I am product 2',
        '3' => 'I am product 3',
    );
 
    // Here we are grabbing the 'id' path variable from the $request object. WP_REST_Request implements ArrayAccess, which allows us to grab properties as though it is an array.
    $id = (string) $request['id'];
 
    if ( isset( $products[ $id ] ) ) {
        // Grab the product.
        $product = $products[ $id ];
 
        // Return the product as a response.
        return rest_ensure_response( $product );
    } else {
        // Return a WP_Error because the request product was not found. In this case we return a 404 because the main resource was not found.
        return new WP_Error( 'rest_product_invalid', esc_html__( 'The product does not exist.', 'my-text-domain' ), array( 'status' => 404 ) );
    }
 
    // If the code somehow executes to here something bad happened return a 500.
    return new WP_Error( 'rest_api_sad', esc_html__( 'Something went horribly wrong.', 'my-text-domain' ), array( 'status' => 500 ) );
}
 
/**
 * This function is where we register our routes for our example endpoint.
 */
function prefix_register_product_routes() {
    // Here we are registering our route for a collection of products.
    register_rest_route( 'my-shop/v1', '/products', 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_products',
    ) );
    // Here we are registering our route for single products. The (?P<id>[\d]+) is our path variable for the ID, which, in this example, can only be some form of positive number.
    register_rest_route( 'my-shop/v1', '/products/(?P<id>[\d]+)', 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_product',
    ) );
}
 
add_action( 'rest_api_init', 'prefix_register_product_routes' );

上面的例子很多。要注意的重要的一点是,在第二条路线中,我们注册,我们添加一个路径变量/(?P [\ d] +)到我们的资源路径/产品。路径变量是一个正则表达式。在这种情况下,它使用[\ d] +表示应该是任何数字字符至少一次。如果您使用资源的数字ID,那么这是一个很好的例子,说明如何使用路径变量。当使用路径变量时,我们现在必须小心,因为用户输入可以匹配什么。

幸运的是,正则表达式将过滤出不是数字的任何东西。但是,如果请求的ID的产品不存在,该怎么办?我们需要做错误处理。您可以在上面的代码示例中看到我们处理错误的基本方法。当您在终端回调中返回WP_Error时,API服务器将自动处理向客户端提供错误。

虽然本节是关于路线,但是我们已经对端点进行了很多的介绍。端点和路由是相互关联的,但它们绝对有区别。

##端点

端点是路由需要映射到的目的地址。对于任何给定的路由,您可以为其注册多个不同的端点。我们将扩展我们的虚拟电子商务插件,以更好地显示路由和端点之间的区别。我们将在/ wp-json / my-shop / v1 / products / route中创建两个端点。一个端点使用HTTP动词GET获取产品,另一个端点使用HTTP动词POST创建新产品。

/**
 * This is our callback function to return our products.
 *
 * @param WP_REST_Request $request This function accepts a rest request to process data.
 */
function prefix_get_products( $request ) {
    // In practice this function would fetch the desired data. Here we are just making stuff up.
    $products = array(
        '1' => 'I am product 1',
        '2' => 'I am product 2',
        '3' => 'I am product 3',
    );
     
    return rest_ensure_response( $products );
}
 
/**
 * This is our callback function to return a single product.
 *
 * @param WP_REST_Request $request This function accepts a rest request to process data.
 */
function prefix_create_product( $request ) {
    // In practice this function would create a product. Here we are just making stuff up.
   return rest_ensure_response( 'Product has been created' );
}
 
/**
 * This function is where we register our routes for our example endpoint.
 */
function prefix_register_product_routes() {
    // Here we are registering our route for a collection of products and creation of products.
    register_rest_route( 'my-shop/v1', '/products', array(
        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_products',
        ),
        array(
            // By using this constant we ensure that when the WP_REST_Server changes, our create endpoints will work as intended.
            'methods'  => WP_REST_Server::CREATABLE,
            // Here we register our callback. The callback is fired when this endpoint is matched by the WP_REST_Server class.
            '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应用于删除资源。
应该使用选项来提供有关我们资源的上下文。
重要的是要注意,每个客户端都不支持这些方法,因为它们在HTTP 1.1中引入。幸运的是,API为这些不幸的情况提供了解决方法。如果要删除资源但无法发送DELETE请求,则可以在请求中使用_method参数或X-HTTP-Method-Override标头。您如何发送POST请求到https://ourawesomesite.com/wp-json/my-shop/v1/products/1?_method=DELETE。现在您将删除产品编号1,即使您的客户端无法在请求中发送适当的HTTP方法,也可能存在阻止DELETE请求的防火墙。

HTTP方法与路由和回调相结合,构成端点的核心。

回调

REST API支持的端点目前只有两种类型的回调方式:回调和permission_callback。主要回调应该处理与资源的交互。权限回调应该处理用户对端点的访问权限。您可以通过在注册端点时添加其他信息来添加额外的回调。然后,您可以钩入rest_pre_dispatch,rest_dispatch_request或rest_post_dispatch钩子来触发新的自定义回调。

端点回调

删除端点的主要回调只能删除资源并在响应中返回它的副本。创建端点的主要回调只能创建资源并返回与新创建的数据匹配的响应。更新回调应该仅修改实际存在的资源。读取回调应该只检索已经存在的数据。考虑到幂等概念是很重要的。

在REST API的上下文中,Idempotence意味着如果向端点发出相同的请求,服务器将以相同的方式处理请求。想像一下,如果我们读取的端点不是幂等的。每当我们向它提出请求时,我们的服务器状态将被请求修改,即使我们只是试图获取数据。这可能是灾难性的。任何时候有人从您的服务器中获取数据,内部会发生变化。重要的是确保读取,更新和删除端点不具有令人讨厌的副作用,并坚持要做的事情。

在REST API中,幂等式的概念与HTTP方法而不是端点回调相关联。使用GET,HEAD,TRACE,OPTIONS,PUT或DELETE的任何回调不应产生任何副作用。 POST请求不是幂等的,通常用于创建资源。如果你创建了一个幂等的创建方法,那么你只会创建一个资源,因为当你做同样的请求时,服务器不会有更多的副作用。对于创建,如果您通过服务器发出相同的请求,则每次都应生成新的资源。

为了限制端点的使用,我们需要注册一个权限回调。

权限回调

权限回调对于使用WordPress REST API的安全性至关重要。如果您有任何不应公开显示的私人数据,那么您需要为您的端点注册权限回调。以下是如何注册权限回调的示例。

/**
 * This is our callback function that embeds our resource in a WP_REST_Response
 */
function prefix_get_private_data() {
    // 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( 'This is private data.' );
}
 
/**
 * This is our callback function that embeds our resource in a WP_REST_Response
 */
function prefix_get_private_data_permissions_check() {
    // Restrict endpoint to only users who have the edit_posts capability.
    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 ) );
    }
 
    // This is a black-listing approach. You could alternatively do this via white-listing, by returning false here and changing the permissions check.
    return true;
}
 
/**
 * 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( 'my-plugin/v1', '/private-data', 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_private_data',
        // Here we register our permissions callback. The callback is fired before the main callback to check if the current user can access the endpoint.
        'permission_callback' => 'prefix_get_private_data_permissions_check',
    ) );
}
 
add_action( 'rest_api_init', 'prefix_register_example_routes' );

如果您尝试此端点,而不启用任何身份验证,那么您也将返回错误响应,从而阻止您看到数据。 身份验证是一个很大的课题,最终将会创建本章的一部分,向您展示如何创建自己的身份验证过程。

参数

当向端点发出请求时,您可能需要指定额外的参数来更改响应。 可以在注册端点时添加这些额外的参数。 我们来看一个如何使用一个端点参数的例子。

/**
 * This is our callback function that embeds our resource in a WP_REST_Response
 */
function prefix_get_colors( $request ) {
    // In practice this function would fetch the desired data. Here we are just making stuff up.
    $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 );
}
 
/**
 * We can use this function to contain our arguments for the example product endpoint.
 */
function prefix_get_color_arguments() {
    $args = array();
    // Here we are registering the schema for the filter argument.
    $args['filter'] = array(
        // description should be a human readable description of the argument.
        'description' => esc_html__( 'The filter parameter is used to filter the collection of colors', 'my-text-domain' ),
        // type specifies the type of data that the argument should be.
        'type'        => 'string',
        // enum specified what values filter can take on.
        'enum'        => array( 'red', 'green', 'blue' ),
    );
    return $args;
}
 
/**
 * 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( 'my-colors/v1', '/colors', 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_colors',
        // Here we register our permissions callback. The callback is fired before the main callback to check if the current user can access the endpoint.
        'args' => prefix_get_color_arguments(),
    ) );
}
 
add_action( 'rest_api_init', 'prefix_register_example_routes' );

我们现在已经为此示例指定了一个过滤器参数。当我们请求端点时,我们可以将参数指定为查询参数。如果我们向https://ourawesomesitem.com/my-colors/v1/colors?filter=blue发出GET请求,我们将只收回我们的集合中的蓝色。您也可以将它们作为身体参数传递到请求正文中,而不是在查询字符串中。要了解查询参数和体参数之间的区别,您应该阅读有关HTTP规范的内容。查询参数实际上位于查询字符串中的URL和body参数直接嵌入到HTTP请求的正文中。

我们已经为我们的端点创建了一个参数,但是我们如何验证参数是一个字符串,并判断它是否匹配红色,绿色或蓝色的值。为此,我们需要为我们的参数指定一个验证回调。

验证

验证和消毒对API的安全性至关重要。验证回调(在WP 4.6+中),在消毒回调之前触发。您应该使用validate_callback作为参数来验证您正在接收的输入是否有效。在参数由主回调处理之前,应该使用sanitize_callback来转换参数输入或清除参数中的不需要的部分。

在上面的示例中,我们需要验证过滤器参数是一个字符串,并且它与红色,绿色或蓝色的值匹配。让我们看一下在validate_callback中添加代码之后的代码。

/**
 * This is our callback function that embeds our resource in a WP_REST_Response
 */
function prefix_get_colors( $request ) {
    // In practice this function would fetch more practical data. Here we are just making stuff up.
    $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 );
}
/**
 * Validate a request argument based on details registered to the route.
 *
 * @param  mixed            $value   Value of the 'filter' argument.
 * @param  WP_REST_Request  $request The current request object.
 * @param  string           $param   Key of the parameter. In this case it is 'filter'.
 * @return WP_Error|boolean
 */
function prefix_filter_arg_validate_callback( $value, $request, $param ) {
    // If the 'filter' argument is not a string return an error.
    if ( ! is_string( $value ) ) {
        return new WP_Error( 'rest_invalid_param', esc_html__( 'The filter argument must be a string.', 'my-text-domain' ), array( 'status' => 400 ) );
    }
 
    // Get the registered attributes for this endpoint request.
    $attributes = $request->get_attributes();
 
    // Grab the filter param schema.
    $args = $attributes['args'][ $param ];
 
    // If the filter param is not a value in our enum then we should return an error as well.
    if ( ! in_array( $value, $args['enum'], true ) ) {
        return new WP_Error( 'rest_invalid_param', sprintf( __( '%s is not one of %s' ), $param, implode( ', ', $args['enum'] ) ), array( 'status' => 400 ) );
    }
}
 
/**
 * We can use this function to contain our arguments for the example product endpoint.
 */
function prefix_get_color_arguments() {
    $args = array();
    // Here we are registering the schema for the filter argument.
    $args['filter'] = array(
        // description should be a human readable description of the argument.
        'description' => esc_html__( 'The filter parameter is used to filter the collection of colors', 'my-text-domain' ),
        // type specifies the type of data that the argument should be.
        'type'        => 'string',
        // enum specified what values filter can take on.
        'enum'        => array( 'red', 'green', 'blue' ),
        // Here we register the validation callback for the filter argument.
        'validate_callback' => 'prefix_filter_arg_validate_callback',
    );
    return $args;
}
 
/**
 * 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( 'my-colors/v1', '/colors', 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_colors',
        // Here we register our permissions callback. The callback is fired before the main callback to check if the current user can access the endpoint.
        'args' => prefix_get_color_arguments(),
    ) );
}
 
add_action( 'rest_api_init', 'prefix_register_example_routes' );

消毒

在上面的例子中,我们不需要使用sanitize_callback,因为我们将输入限制在我们枚举中的值。 如果我们没有严格的验证并接受任何字符串作为参数,我们一定需要注册一个sanitize_callback。 如果我们要更新内容字段,用户输入的内容如“alert”(“ZOMG Hacking you”),该怎么办? 字段值可能是可执行脚本。 要删除不需要的数据或将数据转换成所需的格式,我们需要为我们的参数注册一个sanitize_callback。 以下是使用WordPress的sanitize_text_field()进行消毒回调的示例:

/**
 * This is our callback function that embeds our resource in a WP_REST_Response.
 *
 * The parameter is already sanitized by this point so we can use it without any worries.
 */
function prefix_get_item( $request ) {
    if ( isset( $request['data'] ) ) {
        return rest_ensure_response( $request['data'] );
    }
 
    return new WP_Error( 'rest_invalid', esc_html__( 'The data parameter is required.', 'my-text-domain' ), array( 'status' => 400 ) );
}
 
/**
 * Validate a request argument based on details registered to the route.
 *
 * @param  mixed            $value   Value of the 'filter' argument.
 * @param  WP_REST_Request  $request The current request object.
 * @param  string           $param   Key of the parameter. In this case it is 'filter'.
 * @return WP_Error|boolean
 */
function prefix_data_arg_validate_callback( $value, $request, $param ) {
    // If the 'data' argument is not a string return an error.
    if ( ! is_string( $value ) ) {
        return new WP_Error( 'rest_invalid_param', esc_html__( 'The filter argument must be a string.', 'my-text-domain' ), array( 'status' => 400 ) );
    }
}
 
/**
 * Sanitize a request argument based on details registered to the route.
 *
 * @param  mixed            $value   Value of the 'filter' argument.
 * @param  WP_REST_Request  $request The current request object.
 * @param  string           $param   Key of the parameter. In this case it is 'filter'.
 * @return WP_Error|boolean
 */
function prefix_data_arg_sanitize_callback( $value, $request, $param ) {
    // It is as simple as returning the sanitized value.
    return sanitize_text_field( $value );
}
 
/**
 * We can use this function to contain our arguments for the example product endpoint.
 */
function prefix_get_data_arguments() {
    $args = array();
    // Here we are registering the schema for the filter argument.
    $args['data'] = array(
        // description should be a human readable description of the argument.
        'description' => esc_html__( 'The data parameter is used to be sanitized and returned in the response.', 'my-text-domain' ),
        // type specifies the type of data that the argument should be.
        'type'        => 'string',
        // Set the argument to be required for the endpoint.
        'required'    => true,
        // We are registering a basic validation callback for the data argument.
        'validate_callback' => 'prefix_data_arg_validate_callback',
        // Here we register the validation callback for the filter argument.
        'sanitize_callback' => 'prefix_data_arg_sanitize_callback',
    );
    return $args;
}
 
/**
 * 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( 'my-plugin/v1', '/sanitized-data', 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_item',
        // Here we register our permissions callback. The callback is fired before the main callback to check if the current user can access the endpoint.
        'args' => prefix_get_data_arguments(),
    ) );
}
 
add_action( 'rest_api_init', 'prefix_register_example_routes' );

概要

我们已经介绍了为WordPress REST API注册端点的基础知识。 路由是我们的端点所在的URI。 端点是回调,方法,参数和其他选项的集合。 当使用register_rest_route()时,每个端点映射到路由。 默认端点可以支持各种HTTP方法,主要回调,权限回调和注册的参数。 我们可以注册端点来覆盖与WordPress交互的任何用例。 端点作为与REST API的核心交互点,但还有许多其他要探索和理解的主题,以充分利用这个强大的API。