深入理解 WordPress `WP_REST_Response` 类的源码:如何通过 `set_data()` 和 `set_status()` 构建响应。

嘿,各位代码界的探险家们,准备好一起深入 WordPress 的心脏了吗?今天,咱们的目标是解剖 WP_REST_Response 这个类,搞清楚它如何用 set_data()set_status() 这两把手术刀,构建出美味可口的 REST API 响应。

开场白:REST API 的语言艺术

想象一下,你是一位外交官,需要向其他国家(也就是客户端)传递信息。REST API 就是你的语言,而 WP_REST_Response 就是你用来撰写外交辞令的文书。一份好的外交辞令,哦不,REST API 响应,需要清晰的数据(信息)和明确的状态(态度)。set_data() 负责填充信息,set_status() 则负责表明态度。

第一幕:WP_REST_Response 类概览

WP_REST_Response 类位于 WordPress 的核心,是构建 REST API 响应的关键。它继承自 WP_HTTP_Response 类,后者是 WordPress 处理 HTTP 响应的基础类。WP_REST_ResponseWP_HTTP_Response 的基础上,增加了更多 REST API 相关的特性,比如链接关系(links)和元数据(metadata)。

咱们先来简单看看它的定义:

/**
 * Core class used to implement a REST response.
 *
 * @since 4.4.0
 */
class WP_REST_Response extends WP_HTTP_Response {

    /**
     * The data for the response.
     *
     * @var mixed
     */
    protected $data;

    /**
     * REST API version.
     *
     * @var string
     */
    protected $api_version;

    /**
     * Links related to the response.
     *
     * @var array
     */
    protected $links = array();

    /**
     * Additional data to pass along.
     *
     * @var array
     */
    protected $meta = array();

    // ... (其他方法)
}

可以看到,$data 存储着响应的主要数据,$links 存储着链接关系,$meta 存储着元数据。这些都是构建一个结构化 REST API 响应的关键要素。

第二幕:set_data()——填充数据的艺术

set_data() 方法负责将数据填充到响应对象中。这个数据可以是任何 PHP 类型,比如数组、对象、字符串、数字等等。

/**
 * Sets the data for the response.
 *
 * @since 4.4.0
 *
 * @param mixed $data Data for the response.
 * @return WP_REST_Response The response object.
 */
public function set_data( $data ) {
    $this->data = $data;
    return $this;
}

这个方法非常简单,就是把传入的 $data 赋值给 $this->data 属性。但它的重要性不容忽视,因为它是响应的核心内容。

例子 1:返回一个简单的字符串

$response = new WP_REST_Response();
$response->set_data( 'Hello, world!' );
$response->set_status( 200 ); // 设置状态码为 200 OK

return rest_ensure_response( $response ); // 确保返回的是 WP_REST_Response 对象

在这个例子中,我们创建了一个 WP_REST_Response 对象,并使用 set_data() 将字符串 "Hello, world!" 设置为响应的数据。然后,我们使用 set_status() 设置 HTTP 状态码为 200 OK。rest_ensure_response() 函数确保返回的是一个 WP_REST_Response 对象,如果传入的不是,它会自动进行转换。

例子 2:返回一个数组

$data = array(
    'name' => 'John Doe',
    'age'  => 30,
    'city' => 'New York',
);

$response = new WP_REST_Response();
$response->set_data( $data );
$response->set_status( 200 );

return rest_ensure_response( $response );

这个例子展示了如何返回一个包含用户信息的数据。客户端会收到一个 JSON 对象,包含 name, age, city 三个属性。

例子 3:返回一个自定义对象

class Person {
    public $name;
    public $age;
    public $city;

    public function __construct( $name, $age, $city ) {
        $this->name = $name;
        $this->age  = $age;
        $this->city = $city;
    }
}

$person = new Person( 'Jane Doe', 25, 'London' );

$response = new WP_REST_Response();
$response->set_data( $person );
$response->set_status( 200 );

return rest_ensure_response( $response );

这个例子展示了如何返回一个自定义对象。WordPress 会自动将这个对象转换为 JSON 格式。

注意事项:

  • 尽量返回结构化的数据,比如数组或对象。这样客户端更容易解析和使用。
  • 避免返回过于复杂的数据结构,这会增加客户端的解析难度。
  • 确保数据类型一致,避免出现数据类型混乱的情况。

第三幕:set_status()——表达态度的艺术

set_status() 方法负责设置 HTTP 状态码,用来表明服务器对请求的处理结果。状态码是非常重要的,它告诉客户端请求是成功了还是失败了,以及失败的原因。

/**
 * Sets the HTTP status code for the response.
 *
 * @since 4.4.0
 *
 * @param int $status HTTP status code.
 * @return WP_REST_Response The response object.
 */
public function set_status( $status ) {
    $this->status = absint( $status );
    return $this;
}

这个方法也很简单,就是把传入的 $status 转换为整数,并赋值给 $this->status 属性。

常见的 HTTP 状态码:

状态码 含义 使用场景
200 OK 请求成功
201 Created 资源创建成功,例如 POST 请求创建新文章
204 No Content 请求成功,但没有内容返回,例如 DELETE 请求成功删除资源
400 Bad Request 请求无效,例如缺少必要的参数,参数格式错误
401 Unauthorized 未授权,需要提供身份验证信息
403 Forbidden 禁止访问,即使提供了身份验证信息也没有权限访问
404 Not Found 资源未找到
405 Method Not Allowed 请求方法不允许,例如使用 GET 方法请求一个只允许 POST 的接口
500 Internal Server Error 服务器内部错误,通常是代码出现了 bug
503 Service Unavailable 服务不可用,例如服务器正在维护

例子 1:请求成功

$response = new WP_REST_Response();
$response->set_data( array( 'message' => '操作成功' ) );
$response->set_status( 200 );

return rest_ensure_response( $response );

这个例子表明请求成功,并返回了一个包含 "操作成功" 消息的数据。

例子 2:资源未找到

$response = new WP_REST_Response();
$response->set_data( array( 'message' => '资源未找到' ) );
$response->set_status( 404 );

return rest_ensure_response( $response );

这个例子表明请求的资源不存在。

例子 3:参数错误

$response = new WP_REST_Response();
$response->set_data( array( 'message' => '参数错误' ) );
$response->set_status( 400 );

return rest_ensure_response( $response );

这个例子表明客户端提供的参数不正确。

注意事项:

  • 选择合适的状态码,准确地表达请求的处理结果。
  • 在错误状态码下,提供详细的错误信息,帮助客户端排查问题。
  • 保持状态码的一致性,避免出现状态码混乱的情况。

第四幕:WP_Error——处理错误的利器

除了使用 set_status() 设置状态码外,还可以使用 WP_Error 类来处理错误。WP_Error 类是 WordPress 中用于处理错误的通用类。

if ( ! current_user_can( 'edit_posts' ) ) {
    return new WP_Error( 'rest_cannot_edit', __( 'Sorry, you are not allowed to edit posts on this site.' ), array( 'status' => rest_authorization_required_code() ) );
}

在这个例子中,如果当前用户没有编辑文章的权限,就返回一个 WP_Error 对象。rest_authorization_required_code() 函数返回一个合适的 HTTP 状态码(通常是 401 或 403),表明权限不足。

WP_Error 对象会自动被 rest_ensure_response() 函数转换为 WP_REST_Response 对象,并设置相应的状态码和数据。

第五幕:rest_ensure_response()——最后的润色

rest_ensure_response() 函数是 WordPress REST API 中非常重要的一个函数。它的作用是确保返回的是一个 WP_REST_Response 对象。如果传入的不是 WP_REST_Response 对象,它会自动进行转换。

/**
 * Ensures that the REST response is a response object (for consistency).
 *
 * @since 4.4.0
 *
 * @param mixed $response Response to check.
 * @return WP_REST_Response If `$response` is a Response object, `$response`, otherwise a `WP_REST_Response`
 *                           object.
 */
function rest_ensure_response( $response ) {
    if ( is_a( $response, 'WP_REST_Response' ) ) {
        return $response;
    }

    $data = $response;
    $response = new WP_REST_Response( $data );

    return $response;
}

可以看到,如果传入的是 WP_REST_Response 对象,就直接返回。否则,就创建一个新的 WP_REST_Response 对象,并将传入的数据设置为该对象的数据。

第六幕:实战演练——创建一个自定义 REST API 接口

现在,让我们来创建一个自定义 REST API 接口,来巩固一下所学的知识。

首先,我们需要注册一个路由:

add_action( 'rest_api_init', function () {
    register_rest_route( 'myplugin/v1', '/books/(?P<id>d+)', array(
        'methods'  => 'GET',
        'callback' => 'my_plugin_get_book',
        'args'     => array(
            'id' => array(
                'validate_callback' => 'is_numeric',
                'sanitize_callback' => 'absint',
            ),
        ),
    ) );
} );

这个代码注册了一个名为 myplugin/v1/books/{id} 的路由,只允许 GET 方法访问。(?P<id>d+) 表示 URL 中的 {id} 是一个数字。'callback' => 'my_plugin_get_book' 指定了处理请求的函数是 my_plugin_get_book()'args' 定义了参数的验证和过滤规则。

接下来,我们需要定义 my_plugin_get_book() 函数:

function my_plugin_get_book( $request ) {
    $id = $request['id'];

    // 假设我们从数据库中获取书籍信息
    $book = get_book_from_database( $id );

    if ( ! $book ) {
        return new WP_Error( 'book_not_found', 'Book not found', array( 'status' => 404 ) );
    }

    $response = new WP_REST_Response();
    $response->set_data( $book );
    $response->set_status( 200 );

    return rest_ensure_response( $response );
}

function get_book_from_database( $id ) {
    // 模拟从数据库中获取书籍信息
    $books = array(
        1 => array( 'id' => 1, 'title' => 'The Lord of the Rings', 'author' => 'J.R.R. Tolkien' ),
        2 => array( 'id' => 2, 'title' => 'Pride and Prejudice', 'author' => 'Jane Austen' ),
    );

    if ( isset( $books[ $id ] ) ) {
        return $books[ $id ];
    }

    return false;
}

在这个函数中,我们首先从请求中获取 ID。然后,我们模拟从数据库中获取书籍信息。如果书籍不存在,就返回一个 WP_Error 对象,并设置状态码为 404。如果书籍存在,就创建一个 WP_REST_Response 对象,并将书籍信息设置为数据,并设置状态码为 200。最后,使用 rest_ensure_response() 函数确保返回的是一个 WP_REST_Response 对象。

第七幕:总结与回顾

今天,我们深入学习了 WordPress WP_REST_Response 类的源码,重点讲解了 set_data()set_status() 这两个方法。我们还学习了如何使用 WP_Error 类来处理错误,以及 rest_ensure_response() 函数的作用。通过实战演练,我们创建了一个自定义 REST API 接口,巩固了所学的知识。

方法/类 功能 作用
WP_REST_Response REST API 响应对象 用于构建 REST API 响应,包含数据、状态码、链接关系、元数据等信息。
set_data() 设置响应的数据 将数据填充到响应对象中,数据可以是任何 PHP 类型。
set_status() 设置 HTTP 状态码 表明服务器对请求的处理结果,例如 200 OK, 404 Not Found, 500 Internal Server Error 等。
WP_Error 错误处理类 用于处理错误,可以包含错误码、错误信息、以及其他相关数据。
rest_ensure_response() 确保返回的是 WP_REST_Response 对象 确保返回的是一个 WP_REST_Response 对象,如果传入的不是,它会自动进行转换。

希望今天的讲座能帮助你更好地理解 WordPress REST API 的工作原理。记住,编写优雅的 REST API 代码,就像写诗一样,需要仔细雕琢每一个字,每一行代码。下次再见!

发表回复

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