WordPress wp_send_json_success
与 wp_send_json_error
的底层输出机制
大家好,今天我们来深入探讨 WordPress 中用于发送 JSON 响应的两个核心函数:wp_send_json_success
和 wp_send_json_error
。这两个函数在 WordPress 开发中扮演着重要的角色,尤其是在处理 AJAX 请求和构建 REST API 时。理解它们的底层机制对于编写健壮、高效的 WordPress 代码至关重要。
1. JSON 数据格式与 HTTP 响应
在深入研究这两个函数之前,我们先回顾一下 JSON (JavaScript Object Notation) 数据格式和 HTTP 响应的基本概念。
-
JSON: 是一种轻量级的数据交换格式,易于阅读和编写,也易于机器解析和生成。它基于 JavaScript 的一个子集,但可以被多种编程语言支持。JSON 数据通常由键值对组成,可以表示简单的数据类型(如字符串、数字、布尔值)以及复杂的数据结构(如对象和数组)。
-
HTTP 响应: 当客户端(例如浏览器)向服务器发送 HTTP 请求时,服务器会返回一个 HTTP 响应。这个响应包含状态码(如 200 OK, 400 Bad Request, 500 Internal Server Error)、HTTP 头信息(例如
Content-Type
,Content-Length
)以及响应体。对于 AJAX 请求和 REST API,响应体通常包含 JSON 数据。
2. wp_send_json_success
函数
wp_send_json_success
函数用于发送成功的 JSON 响应。它的原型如下:
/**
* Sends a JSON response indicating success.
*
* @since 4.5.0
*
* @param mixed $data Optional. Data to encode as JSON, then print and die. Default null.
*/
function wp_send_json_success( $data = null ) {
$response = array( 'success' => true );
if ( isset( $data ) ) {
$response['data'] = $data;
}
wp_send_json( $response );
}
底层机制分析:
-
构建响应数组: 函数首先创建一个包含
'success' => true
键值对的数组$response
。这是标识成功响应的关键。 -
添加数据(可选): 如果提供了
$data
参数,它将被添加到$response
数组中,键名为'data'
。这意味着你可以在成功响应中包含任何类型的数据,例如用户 ID、文章列表、更新后的配置等等。 -
调用
wp_send_json
函数: 最后,函数调用wp_send_json
函数来实际发送 JSON 响应。wp_send_json
是 WordPress 中用于发送 JSON 响应的核心函数,我们稍后会详细分析它。
示例:
<?php
// 假设我们有一个函数来处理用户注册
function process_registration( $username, $password ) {
// 验证用户名和密码
if ( empty( $username ) || empty( $password ) ) {
return new WP_Error( 'invalid_credentials', '用户名和密码不能为空。' );
}
// 创建用户
$user_id = wp_create_user( $username, $password );
if ( is_wp_error( $user_id ) ) {
return $user_id; // 返回 WP_Error 对象
}
// 返回用户 ID 作为成功响应的数据
return $user_id;
}
// 处理 AJAX 请求
if ( isset( $_POST['action'] ) && $_POST['action'] == 'register_user' ) {
$username = isset( $_POST['username'] ) ? sanitize_text_field( $_POST['username'] ) : '';
$password = isset( $_POST['password'] ) ? sanitize_text_field( $_POST['password'] ) : '';
$result = process_registration( $username, $password );
if ( is_wp_error( $result ) ) {
wp_send_json_error( $result->get_error_message() );
} else {
wp_send_json_success( array( 'user_id' => $result ) );
}
}
?>
在这个例子中,如果用户注册成功,process_registration
函数会返回用户 ID。wp_send_json_success
函数会将用户 ID 包装在 data
键下,并发送 JSON 响应。
输出的 JSON 结构:
{
"success": true,
"data": {
"user_id": 5
}
}
3. wp_send_json_error
函数
wp_send_json_error
函数用于发送错误的 JSON 响应。它的原型如下:
/**
* Sends a JSON response indicating failure.
*
* @since 4.5.0
*
* @param mixed $data Optional. Data to encode as JSON, then print and die. Default null.
* @param int $status_code Optional. The HTTP status code to send. Default 200.
*/
function wp_send_json_error( $data = null, $status_code = null ) {
$response = array( 'success' => false );
if ( isset( $data ) ) {
$response['data'] = $data;
}
wp_send_json( $response, $status_code );
}
底层机制分析:
-
构建响应数组: 函数创建一个包含
'success' => false
键值对的数组$response
。这是标识错误响应的关键。 -
添加数据(可选): 如果提供了
$data
参数,它将被添加到$response
数组中,键名为'data'
。通常,$data
参数包含错误消息、错误代码或其他与错误相关的信息。 -
调用
wp_send_json
函数: 函数调用wp_send_json
函数来实际发送 JSON 响应。与wp_send_json_success
不同的是,wp_send_json_error
允许你指定一个可选的 HTTP 状态码$status_code
。默认情况下,它使用 200 OK 状态码,但这通常是不合适的,因为 200 OK 意味着请求成功。你应该使用适当的错误状态码,例如 400 Bad Request、403 Forbidden、404 Not Found 或 500 Internal Server Error。
示例:
<?php
// 在上面的注册例子中,如果用户名密码为空,将会返回错误,使用 wp_send_json_error。
// 处理 AJAX 请求
if ( isset( $_POST['action'] ) && $_POST['action'] == 'register_user' ) {
$username = isset( $_POST['username'] ) ? sanitize_text_field( $_POST['username'] ) : '';
$password = isset( $_POST['password'] ) ? sanitize_text_field( $_POST['password'] ) : '';
$result = process_registration( $username, $password );
if ( is_wp_error( $result ) ) {
wp_send_json_error( $result->get_error_message(), 400 );
} else {
wp_send_json_success( array( 'user_id' => $result ) );
}
}
?>
在这个例子中,如果 process_registration
函数返回一个 WP_Error
对象,wp_send_json_error
函数会将错误消息包装在 data
键下,并发送 JSON 响应,同时设置 HTTP 状态码为 400 Bad Request。
输出的 JSON 结构:
{
"success": false,
"data": "用户名和密码不能为空。"
}
HTTP 状态码: 400 Bad Request
4. wp_send_json
函数
wp_send_json
函数是 wp_send_json_success
和 wp_send_json_error
的核心,它负责设置 HTTP 头信息并输出 JSON 数据。它的原型如下:
/**
* Sends a JSON response to the client, including sending the proper headers.
*
* @since 4.1.0
*
* @param mixed $response Variable (usually array or object) to be encoded as JSON and sent to the client.
* @param int $status Optional. The HTTP status code to send. Default 200.
*/
function wp_send_json( $response = null, $status = null ) {
// phpcs:ignore WordPress.Security.NoExitAfterRedirect.wp_send_json_exit
@header( 'Content-Type: application/json; charset=' . get_option( 'blog_charset' ) );
wp_send_json_options( $response, $status );
}
底层机制分析:
-
设置
Content-Type
头信息: 函数首先使用header()
函数设置Content-Type
头信息为application/json; charset=
,其中` 是 WordPress 博客的字符集(通常是 UTF-8)。这告诉客户端响应体包含 JSON 数据,并且使用指定的字符集进行编码。
get_option( ‘blog_charset’ )`函数获取博客的字符集配置项。 -
调用
wp_send_json_options
函数: 函数然后调用wp_send_json_options
函数来实际编码 JSON 数据并输出。
5. wp_send_json_options
函数
wp_send_json_options
函数是实际执行 JSON 编码和输出的函数。 它的原型如下:
/**
* Handles JSONP callback and sends the result to the client.
*
* @since 4.4.0
*
* @param mixed $response Variable (usually array or object) to be encoded as JSON and sent to the client.
* @param int $status Optional. The HTTP status code to send. Default 200.
* @param int $options Optional. Options to be passed to json_encode(). Default 0.
*/
function wp_send_json_options( $response = null, $status = null, $options = 0 ) {
global $wp_json_encoder;
if ( ! is_null( $status ) ) {
status_header( absint( $status ) );
}
// If available, use the faster json_encode.
if ( function_exists( 'json_encode' ) ) {
$encoded = json_encode( $response, $options );
if ( false === $encoded ) {
wp_die( 'JSON encoding failed: ' . json_last_error_msg() );
}
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo $encoded;
} else {
if ( ! isset( $wp_json_encoder ) ) {
require_once ABSPATH . WPINC . '/class-json.php';
$wp_json_encoder = new WP_JSON_Encoder();
}
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo $wp_json_encoder->encode( $response );
}
die();
}
底层机制分析:
-
设置 HTTP 状态码: 如果提供了
$status
参数,函数会使用status_header()
函数设置 HTTP 状态码。status_header()
函数是 WordPress 中用于设置 HTTP 状态码的函数。 -
JSON 编码: 函数使用
json_encode()
函数将$response
数据编码为 JSON 字符串。json_encode()
是 PHP 内置的函数,用于将 PHP 变量转换为 JSON 字符串。$options
参数允许你传递额外的选项给json_encode()
函数,例如JSON_PRETTY_PRINT
用于格式化 JSON 输出。如果json_encode()
函数失败,函数会使用wp_die()
函数终止脚本执行并显示错误消息。 -
输出 JSON 数据: 函数使用
echo
语句输出 JSON 字符串。 -
终止脚本执行: 函数使用
die()
函数终止脚本执行。这是非常重要的,因为在发送 JSON 响应后,你通常不希望继续执行任何其他代码。
6. 总结与最佳实践
wp_send_json_success
和 wp_send_json_error
是 WordPress 中用于发送 JSON 响应的便捷函数。它们基于 wp_send_json
和 wp_send_json_options
函数,这些函数负责设置 HTTP 头信息、编码 JSON 数据并输出。
总结 wp_send_json_success
和 wp_send_json_error
的区别:
特性 | wp_send_json_success |
wp_send_json_error |
---|---|---|
success 键值 |
true |
false |
默认状态码 | 200 OK | 200 OK |
适用场景 | 请求成功 | 请求失败 |
最佳实践:
- 始终使用适当的 HTTP 状态码。对于成功的响应,使用 200 OK 或 201 Created。对于错误的响应,使用 400 Bad Request、403 Forbidden、404 Not Found 或 500 Internal Server Error 等。
- 在错误响应中提供有用的错误消息。这有助于客户端了解发生了什么错误并采取适当的措施。
- 对输入数据进行验证和清理,以防止安全漏洞,例如跨站脚本攻击 (XSS) 和 SQL 注入。
- 考虑使用
JSON_PRETTY_PRINT
选项来格式化 JSON 输出,以便于调试。 - 确保你的 WordPress 博客的字符集设置为 UTF-8,以避免编码问题。
- 利用 WordPress 的
WP_Error
对象来处理错误,并使用wp_send_json_error
函数发送错误响应。 - 避免在发送 JSON 响应后继续执行任何其他代码。使用
die()
函数终止脚本执行。
7. 一个完整的例子:使用 wp_send_json_success
和 wp_send_json_error
构建一个简单的 API 端点
假设我们想要创建一个 API 端点,允许客户端获取特定文章的信息。
<?php
/**
* Plugin Name: Simple API Endpoint
*/
// 注册 API 端点
add_action( 'rest_api_init', 'register_article_endpoint' );
function register_article_endpoint() {
register_rest_route(
'myplugin/v1', // 命名空间
'/article/(?P<id>d+)', // 路由,(?P<id>d+) 表示一个名为 id 的数字参数
array(
'methods' => 'GET',
'callback' => 'get_article_data',
'args' => array(
'id' => array(
'validate_callback' => 'rest_validate_request_arg', // 验证参数是否有效
'sanitize_callback' => 'absint', // 将参数转换为整数
),
),
)
);
}
// API 端点回调函数
function get_article_data( $request ) {
$article_id = $request['id'];
// 获取文章
$article = get_post( $article_id );
if ( empty( $article ) ) {
return new WP_Error( 'article_not_found', '找不到文章。', array( 'status' => 404 ) );
}
// 构建响应数据
$data = array(
'id' => $article->ID,
'title' => get_the_title( $article ),
'content' => apply_filters('the_content', $article->post_content),
'author' => get_the_author_meta( 'display_name', $article->post_author ),
'date' => get_the_date( 'Y-m-d H:i:s', $article ),
);
// 发送 JSON 响应
return rest_ensure_response( $data ); // rest_ensure_response会自动使用wp_send_json_success或者wp_send_json_error
}
// 确保是数字
function rest_validate_request_arg( $value, $request, $param ) {
$attributes = $request->get_attributes();
$args = isset( $attributes['args'] ) ? $attributes['args'][$param] : array();
$isValid = true;
if ( isset( $args['type'] ) && 'integer' == $args['type'] ) {
$isValid = is_numeric( $value );
}
return $isValid;
}
在这个例子中,我们使用 register_rest_route
函数注册了一个 API 端点 myplugin/v1/article/<id>
。当客户端发送 GET 请求到这个端点时,get_article_data
函数会被调用。这个函数会获取指定 ID 的文章信息,并将其包装在 JSON 响应中发送给客户端。如果文章不存在,函数会返回一个 WP_Error
对象,rest_ensure_response
函数会自动将其转换为一个错误的 JSON 响应,并设置 HTTP 状态码为 404 Not Found。
- 关于
rest_ensure_response
函数
在上面的例子中,我们使用了 rest_ensure_response
函数来发送 JSON 响应。这个函数是一个非常方便的函数,它可以自动将数据转换为一个 WP_REST_Response
对象,然后使用 wp_send_json_success
或 wp_send_json_error
函数发送 JSON 响应。 如果传入WP_Error
对象,会自动使用wp_send_json_error
。
- 与早期版本 WordPress 的兼容性
在 WordPress 4.5 之前,没有 wp_send_json_success
和 wp_send_json_error
函数。如果你需要支持更早版本的 WordPress,你可以手动构建 JSON 响应并使用 wp_send_json
函数发送。
- 避免常见的错误
- 忘记设置
Content-Type
头信息: 如果你忘记设置Content-Type
头信息为application/json
,客户端可能无法正确解析 JSON 数据。 - 在发送 JSON 响应后继续执行代码: 这可能会导致意外的输出,并破坏 JSON 响应的格式。
- 未正确处理错误: 如果你的代码中出现错误,但你没有正确处理它,可能会导致服务器崩溃或返回不正确的 JSON 响应。
- 未对输入数据进行验证和清理: 这可能会导致安全漏洞。
- 使用不正确的 HTTP 状态码: 使用不正确的 HTTP 状态码可能会导致客户端难以理解发生了什么错误。
总结一下,wp_send_json_success
和wp_send_json_error
提供了一种规范化的方式来发送 JSON 响应,并且与 WordPress 的其他 API 很好地集成,同时需要注意正确设置 HTTP 状态码和处理错误。