概述

API中的响应是我们想要的所有数据。如果我们在要求中犯了一个错误,我们的响应数据也应告知我们发生错误。WordPress REST API中的响应应返回我们要求的数据或错误消息。API中的响应由WP_REST_Response班级,是API的三个基础设施类之一。

wp_rest_response

WP_REST_Response扩展WordPressWP_HTTP_Response类,使我们访问响应标头,响应状态代码和响应数据。

// The following code will not do anything and just serves as a demonstration.
$response = new WP_REST_Response( 'This is some data' );

// To get the response data we can use this method. It should equal 'This is some data'.
$our_data = $response->get_data();

// To access the HTTP status code we can use this method. The most common status code is probably 200, which means OK!
$our_status = $response->get_status();

// To access the HTTP response headers we can use this method.
$our_headers = $response->get_headers();

以上非常简单,并向您展示如何从响应中获得所需的东西。这WP_REST_Response将事情进一步。您可以访问匹配的路由以获取对回溯的响应,该响应来自响应。$response->get_matched_route()$response->get_matched_handler()将返回为产生我们响应的端点注册的选项。这些对于记录API可能很有用。响应类还可以帮助我们解决错误处理。

错误处理

如果我们的要求出现了极大的错误,我们可以返回WP_Error我们的端点回调中的对象解释了出了什么问题,这样:

// Register our mock batch endpoint.
function prefix_register_broken_route() {
    register_rest_route( 'my-namespace/v1', '/broken', array(
        // Supported methods for this endpoint. WP_REST_Server::READABLE translates to GET.
        'methods' => WP_REST_Server::READABLE,
        // Register the callback for the endpoint.
        'callback' => 'prefix_get_an_error',
    ) );
}

add_action( 'rest_api_init', 'prefix_register_broken_route' );

/**
 * Our registered endpoint callback. Notice how we are passing in $request as an argument.
 * By default, the WP_REST_Server will pass in the matched request object to our callback.
 *
 * @param WP_REST_Request $request The current matched request object.
 */
function prefix_get_an_error( $request ) {
    return new WP_Error( 'oops', esc_html__( 'This endpoint is currently broken, try another endpoint, I promise the API is cool! EEEK!!!!', 'my-textdomain' ), array( 'status' => 400 ) );
}

这是一个愚蠢的例子,但它涉及一些关键事情。最重要的是要理解的是,WordPress REST API将自动处理更改 wp_error 将对象进入包含您数据的HTTP响应。当您在WP_Error对象您的HTTP响应状态代码将具有该值。当您需要使用其他错误代码(例如404)来获取未找到的内容,或者403用于禁止访问时,这非常方便。我们要做的就是让我们的端点回调返回请求和WP_REST_Server课程对我们来说将处理许多非常重要的事情。

响应课程还有其他很酷的事情可以帮助我们,例如链接。

链接

如果我们想获得该帖子的帖子和第一个评论怎么办?我们会编写一个单独的端点来处理此用例吗?如果这样做,我们将需要开始添加大量端点来处理各种小用例,并且我们的API索引会很快肿。响应链接为我们提供了一种在API可以理解的资源之间形成关系的方法。API实现了用于资源链接的称为HAL的标准。让我们看一下我们的帖子和评论示例,最好为每个资源提供路线。

假设我们有ID = 1的帖子,并注释ID = 3。注释已分配给帖子1,因此实际上两个资源可以在路线上使用/my-namespace/v1/posts/1/my-namespace/v1/comments/3。我们将添加指向响应的链接,以创建它们之间的关系。让我们首先从评论的角度看一下。

// Register our mock endpoints.
function prefix_register_my_routes() {
    register_rest_route( 'my-namespace/v1', '/posts/(?P<id>[\d]+)', array(
        // Supported methods for this endpoint. WP_REST_Server::READABLE translates to GET.
        'methods' => WP_REST_Server::READABLE,
        // Register the callback for the endpoint.
        'callback' => 'prefix_get_rest_post',
    ) );
    register_rest_route( 'my-namespace/v1', '/comments', array(
        // Supported methods for this endpoint. WP_REST_Server::READABLE translates to GET.
        'methods' => WP_REST_Server::READABLE,
        // Register the callback for the endpoint.
        'callback' => 'prefix_get_rest_comments',
        // Register the post argument to limit results to a specific post parent.
        'args' => array(
            'post' => array(
                'description' => esc_html__( 'The post ID that the comment is assigned to.', 'my-textdomain' ),
                'type'        => 'integer',
                'required'    => true,
            ),
        ),
    ) );
    register_rest_route( 'my-namespace/v1', '/comments/(?P<id>[\d]+)', array(
        // Supported methods for this endpoint. WP_REST_Server::READABLE translates to GET.
        'methods' => WP_REST_Server::READABLE,
        // Register the callback for the endpoint.
        'callback' => 'prefix_get_rest_comment',
    ) );
}

add_action( 'rest_api_init', 'prefix_register_my_routes' );

// Grab a post.
function prefix_get_rest_post( $request ) {
    $id = (int) $request['id'];
    $post = get_post( $id );

    $response = rest_ensure_response( array( $post ) );

    $response->add_links( prefix_prepare_post_links( $post ) );

    return $response;
}

// Prepare post links.
function prefix_prepare_post_links( $post ) {
    $links = array();

    $replies_url = rest_url( 'my-namespace/v1/comments' );
    $replies_url = add_query_arg( 'post', $post->ID, $replies_url );
    $links['replies'] = array(
		'href'         => $replies_url,
		'embeddable'   => true,
    );

    return $links;
}

// Grab a comments.
function prefix_get_rest_comments( $request ) {
    if ( ! isset( $request['post'] ) ) {
        return new WP_Error( 'rest_bad_request', esc_html__( 'You must specify the post parameter for this request.', 'my-text-domain' ), array( 'status' => 400 ) );
    }

    $data = array();

    $comments = get_comments( array( 'post__in' => $request['post'] ) );

    if ( empty( $comments ) ) {
        return array();
    }

    foreach( $comments as $comment ) {
        $response = rest_ensure_response( $comment );
        $response->add_links( prefix_prepare_comment_links( $comment ) );
        $data[] = prefix_prepare_for_collection( $response );
    }

    $response = rest_ensure_response( $data );
    return $response;
}

// Grab a comment.
function prefix_get_rest_comment( $request ) {
    $id = (int) $request['id'];
    $post = get_comment( $id );

    $response = rest_ensure_response( $comment );

    $response->add_links( prefix_prepare_comment_links( $comment ) );

    return $response;
}

// Prepare comment links.
function prefix_prepare_comment_links( $comment ) {
    $links = array();
    if ( 0 !== (int) $comment->comment_post_ID ) {
        $post = get_post( $comment->comment_post_ID );
        if ( ! empty( $post->ID ) ) {
        $links['up'] = array(
                'href'       => rest_url( 'my-namespace/v1/posts/' . $comment->comment_post_ID ),
                'embeddable' => true,
                'post_type'  => $post->post_type,
            );
        }
    }
    return $links;
}

/**
 * Prepare a response for inserting into a collection of responses.
 *
 * This is lifted from WP_REST_Controller class in the WP REST API v2 plugin.
 *
 * @param WP_REST_Response $response Response object.
 * @return array Response data, ready for insertion into collection data.
 */
function prefix_prepare_for_collection( $response ) {
	if ( ! ( $response instanceof WP_REST_Response ) ) {
		return $response;
	}

	$data = (array) $response->get_data();
	$server = rest_get_server();

	if ( method_exists( $server, 'get_compact_response_links' ) ) {
		$links = call_user_func( array( $server, 'get_compact_response_links' ), $response );
	} else {
		$links = call_user_func( array( $server, 'get_response_links' ), $response );
	}

	if ( ! empty( $links ) ) {
		$data['_links'] = $links;
	}

	return $data;
}

如上所示,我们正在使用链接来创建资源之间的关系。如果帖子有注释,我们的端点回调将添加指定“邮政参数”以匹配我们当前帖子ID的注释路由的链接。因此,如果您要遵循该路线,您现在将获得具有分配的发布ID的评论。如果您搜索评论,则每个评论将在帖子上具有链接点“`up”。使用HAL规范在链接中具有特殊含义。如果我们遵循链接进行评论,那么我们将退还给评论父母的帖子。链接非常棒,但是它会变得更好。

WordPress REST API还支持称为嵌入的内容。如果您在我们添加的两个链接中都注意到,我们指定了embeddable => true。这使我们能够将链接的数据嵌入回复中。因此,如果我们想获取评论3及其分配的帖子,我们可以提出此请求https://ourawesomesite.com/wp-json/my-namespace/v1/comments/3?_embed。这_embed参数告诉API,我们希望我们请求的所有可嵌入资源链接也添加到API中。使用嵌入是性能增益,因为在一个HTTP请求中都处理了多个资源。

嵌入和链接的明智使用使WordPress REST API非常灵活且功能强大,可与WordPress互动。

By zhuon

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注