各位观众老爷们,大家好!今天咱们来聊聊 WordPress REST API 里一个挺重要的函数:get_rest_response()
。这家伙看起来不起眼,实际上它在统一 WordPress REST API 的响应格式方面,扮演着关键角色。咱们的目标是扒开它的源码,看看它到底做了些什么,以及如何利用它来构建更规范的 API。
一、开场白:为什么需要统一响应格式?
想象一下,你正在做一个前端应用,需要从不同的 API 接口获取数据。如果每个接口返回的数据格式都不一样,那你的代码岂不是要针对每个接口写一堆解析逻辑?这简直是噩梦!
统一的响应格式可以解决这个问题。它可以让你的前端代码更加简洁、易于维护,并且可以减少出错的可能性。
WordPress REST API 就是这样做的。它通过 get_rest_response()
函数,尽可能地将所有 API 响应统一成一种标准格式。
二、get_rest_response()
的基本用法
首先,我们来看看 get_rest_response()
函数的基本用法。
<?php
/**
* Retrieves a REST response.
*
* Converts different data types into a REST response.
*
* @since 4.7.0
*
* @param mixed $data Response data.
* @param int $status Optional. The HTTP status code. Default 200.
*
* @return WP_REST_Response REST response.
*/
function get_rest_response( $data, $status = 200 ) {
return new WP_REST_Response( $data, $status );
}
这个函数接收两个参数:
$data
:要返回的数据。可以是任何类型,例如数组、对象、字符串等等。$status
:HTTP 状态码,默认为 200 (OK)。
它会返回一个 WP_REST_Response
对象。这个对象包含了所有关于响应的信息,例如数据、状态码、头部等等。
三、WP_REST_Response
对象:响应的容器
WP_REST_Response
类是 WordPress REST API 中用于封装响应的核心类。它提供了一系列方法来设置和获取响应的各个部分。
下面是一些常用的方法:
方法名 | 作用 |
---|---|
set_data( $data ) |
设置响应的数据。 |
get_data() |
获取响应的数据。 |
set_status( $status ) |
设置 HTTP 状态码。 |
get_status() |
获取 HTTP 状态码。 |
header( $key, $value ) |
设置响应头。 |
get_headers() |
获取所有响应头。 |
add_link( $rel, $href, $attributes = array() ) |
添加一个链接到响应中,用于 HATEOAS (Hypermedia as the Engine of Application State)。 |
remove_link( $rel ) |
移除指定关系的链接。 |
四、get_rest_response()
的源码剖析:关键逻辑
虽然 get_rest_response()
函数本身很简单,但它背后的逻辑却很关键。它实际上创建了一个 WP_REST_Response
对象,并将数据和状态码传递给它。
我们深入 WP_REST_Response
类,来看看它如何处理数据。
<?php
/**
* Core class used to implement a REST response.
*
* @since 4.4.0
*/
class WP_REST_Response {
/**
* Response data.
*
* @var mixed
*/
protected $data;
/**
* Response status code.
*
* @var int
*/
protected $status = 200;
/**
* Response headers.
*
* @var array
*/
protected $headers = array();
/**
* Response links.
*
* @var array
*/
protected $links = array();
/**
* Constructor.
*
* @param mixed $data Optional. Response data. Default null.
* @param int $status Optional. The HTTP status code. Default 200.
* @param array $headers Optional. Response headers. Default array().
*/
public function __construct( $data = null, $status = 200, $headers = array() ) {
$this->set_data( $data );
$this->set_status( $status );
$this->set_headers( $headers );
}
/**
* Sets the data for the response.
*
* @param mixed $data Data for the response.
*/
public function set_data( $data ) {
$this->data = $data;
}
/**
* Retrieves the data for the response.
*
* @return mixed Data for the response.
*/
public function get_data() {
return $this->data;
}
/**
* Sets the HTTP status code.
*
* @param int $status HTTP status code.
*/
public function set_status( $status ) {
$this->status = absint( $status );
}
/**
* Retrieves the HTTP status code.
*
* @return int HTTP status code.
*/
public function get_status() {
return $this->status;
}
/**
* Sets a HTTP header.
*
* @param string $key Header name.
* @param string $value Header value.
*/
public function header( $key, $value ) {
$this->headers[ $key ] = $value;
}
/**
* Sets HTTP headers.
*
* @param array $headers Map of header name to header value.
*/
public function set_headers( $headers ) {
$this->headers = wp_parse_args( $headers, $this->headers );
}
/**
* Retrieves all HTTP headers.
*
* @return array Map of header name to header value.
*/
public function get_headers() {
return $this->headers;
}
/**
* Adds a link to the response.
*
* @param string $rel Link relation.
* @param string $href Link URL.
* @param array $attributes Optional. Link attributes. Default array().
*/
public function add_link( $rel, $href, $attributes = array() ) {
if ( empty( $this->links[ $rel ] ) ) {
$this->links[ $rel ] = array();
}
$this->links[ $rel ][] = array(
'href' => $href,
'attributes' => $attributes,
);
}
/**
* Removes a link from the response.
*
* @param string $rel Link relation.
*/
public function remove_link( $rel ) {
unset( $this->links[ $rel ] );
}
/**
* Retrieves all links.
*
* @return array Map of link relation to array of links.
*/
public function get_links() {
return $this->links;
}
}
可以看到,WP_REST_Response
类主要负责存储和管理响应的数据、状态码、头部和链接。它并没有做太多的数据处理,而是将数据原封不动地保存下来。
五、数据序列化:将数据转换成 JSON
虽然 WP_REST_Response
类本身不负责数据序列化,但 WordPress REST API 会在发送响应之前,将数据转换成 JSON 格式。这个过程是由 rest_do_request()
函数触发的。
<?php
/**
* Executes a REST request.
*
* Primarily used to execute a request from another endpoint, or internally.
*
* @since 4.4.0
*
* @param WP_REST_Request $request Request to execute.
*
* @return WP_REST_Response|WP_Error Response from the endpoint.
*/
function rest_do_request( $request ) {
// ... (省略部分代码)
/**
* Filters the REST response before sending to the client.
*
* Allows modification of the response before returning.
*
* @since 4.4.0
*
* @param WP_REST_Response $response The REST response.
* @param WP_REST_Request $request The REST request.
*/
$response = apply_filters( 'rest_post_dispatch', $response, $request );
// Convert the response to data for output.
$data = rest_get_server()->transform_response_to_data( $response, $request );
// ... (省略部分代码)
}
可以看到,rest_do_request()
函数调用了 rest_get_server()->transform_response_to_data()
方法,将 WP_REST_Response
对象转换成用于输出的数据。
WP_REST_Server
类的 transform_response_to_data()
方法会调用 wp_json_encode()
函数,将数据转换成 JSON 格式。
<?php
/**
* Transforms a REST response to data suitable for outputting.
*
* @param WP_REST_Response $response The response to transform.
* @param WP_REST_Request $request The request associated with the response.
* @return array|string The data to output.
*/
public function transform_response_to_data( $response, $request ) {
$data = $response->get_data();
if ( is_object( $data ) && method_exists( $data, 'jsonSerialize' ) ) {
$data = $data->jsonSerialize();
}
// Ensure we're not encoding objects, for compatibility with pre-WP 5.3.
if ( is_object( $data ) ) {
$data = (array) $data;
}
/**
* Filters the data returned from a REST API response.
*
* @since 4.4.0
*
* @param mixed $data The response data.
* @param WP_REST_Response $response The REST response.
* @param WP_REST_Request $request The REST request.
*/
$data = apply_filters( 'rest_prepare_response', $data, $response, $request );
if ( isset( $_GET['_jsonp'] ) ) {
return $data;
}
return wp_json_encode( $data );
}
六、自定义响应格式:rest_prepare_response
过滤器
如果你想自定义 WordPress REST API 的响应格式,可以使用 rest_prepare_response
过滤器。这个过滤器允许你在数据被转换成 JSON 之前,对数据进行修改。
例如,你可以添加一些额外的元数据到响应中:
<?php
add_filter( 'rest_prepare_response', 'my_custom_rest_response', 10, 3 );
function my_custom_rest_response( $data, $response, $request ) {
$data['custom_field'] = 'Hello, world!';
return $data;
}
这段代码会在每个 API 响应中添加一个 custom_field
字段,其值为 "Hello, world!"。
七、错误处理:WP_Error
对象
WordPress REST API 使用 WP_Error
对象来表示错误。WP_Error
对象包含错误代码、错误消息和错误数据。
<?php
$error = new WP_Error( 'invalid_parameter', 'The parameter is invalid.', array( 'status' => 400 ) );
return $error;
当 API 发生错误时,你可以返回一个 WP_Error
对象。WordPress REST API 会自动将 WP_Error
对象转换成 JSON 格式的错误响应。
错误响应的格式如下:
{
"code": "invalid_parameter",
"message": "The parameter is invalid.",
"data": {
"status": 400
}
}
八、HATEOAS:让 API 具有可发现性
HATEOAS (Hypermedia as the Engine of Application State) 是一种 API 设计风格,它允许客户端通过 API 响应中的链接,发现 API 的功能。
WordPress REST API 支持 HATEOAS。你可以使用 WP_REST_Response
类的 add_link()
方法,在响应中添加链接。
例如,你可以添加一个链接到文章的评论列表:
<?php
$response = get_rest_response( $data );
$response->add_link( 'replies', rest_url( 'wp/v2/comments?post=' . $post_id ) );
return $response;
这段代码会在响应中添加一个 replies
链接,指向文章的评论列表 API 接口。
九、一个完整的例子
让我们来看一个完整的例子,展示如何使用 get_rest_response()
函数来构建一个简单的 API 接口。
<?php
/**
* Registers a custom REST route.
*/
add_action( 'rest_api_init', function () {
register_rest_route( 'my-plugin/v1', '/hello', array(
'methods' => 'GET',
'callback' => 'my_plugin_hello_world',
) );
} );
/**
* Handles the custom REST route.
*
* @param WP_REST_Request $request Full data about the request.
* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
*/
function my_plugin_hello_world( $request ) {
$name = $request->get_param( 'name' );
if ( empty( $name ) ) {
return new WP_Error( 'missing_name', 'You must specify a name.', array( 'status' => 400 ) );
}
$data = array(
'message' => 'Hello, ' . $name . '!',
);
return get_rest_response( $data );
}
这段代码注册了一个名为 my-plugin/v1/hello
的 API 接口。当客户端发送 GET 请求到这个接口时,my_plugin_hello_world()
函数会被调用。
my_plugin_hello_world()
函数会获取 name
参数,并返回一个包含问候语的 JSON 响应。如果 name
参数为空,则返回一个 WP_Error
对象。
十、总结
get_rest_response()
函数是 WordPress REST API 中一个非常重要的函数。它负责将数据转换成 WP_REST_Response
对象,从而统一 API 的响应格式。
通过 rest_prepare_response
过滤器,你可以自定义 API 的响应格式,添加额外的元数据到响应中。
通过 WP_Error
对象,你可以处理 API 错误,并返回 JSON 格式的错误响应。
希望今天的讲解对大家有所帮助!祝大家编码愉快!