至少有三种方法可以在 WordPress 插件或主题中实现 Ajax 端点。Admin-Ajax 是永远存在的东西,而 WP_REST 是“新”的方式,重写规则则是另一种方法。我将用代码示例解释所有三种变体,并尝试找出优缺点。
Admin-Ajax
自 WordPress 2.1.0 版起,admin-ajax.php
文件位于 wp-admin 目录中。它的名字暗示管理员只能使用,但它可以用于未经身份验证和身份验证的请求。
对该文件的请求将启动 WordPress 核心、主题(和子主题)functions.php 和插件,但不会以全局 WP_Query 执行或模板解析结束。只要$_REQUEST['action']
提供了值,它就可以用于任何类型的请求方法(GET、POST、PUT、PATCH、DELETE)。此操作值用于触发操作。如果没有注册动作处理程序,则返回一个字符串0
。
基本的未经身份验证的 Admin-Ajax 示例
<?php
namespace PublicFunctionOrg\WordPress\CodeSamples;
// ------------------------------------------------
// /wp-admin/admin-ajax.php?action=my_action
// ------------------------------------------------
function my_unauthorized_action_handler(){
$latestPostTitles = array_map(function($post){
return $post->post_title;
}, get_posts());
wp_send_json($latestPostTitles);
exit;
}
add_action('wp_ajax_nopriv_my_action',__NAMESPACE__.'\my_unauthorized_action_handler');
// 大多数情况下,您希望授权用户也能够使用公共端点
add_action('wp_ajax_my_action',__NAMESPACE__.'\my_unauthorized_action_handler');
通过这几行代码,我们可以使用 URL 调用我们全新的 Ajax 端点/wp-admin/admin-ajax.php?action=my_action
。请务必注意,该wp_ajax_noproiv_{action}
操作仅在您的请求未通过身份验证时才有效。如果您在浏览器中有一个正在运行的登录会话,则响应将为0
. 因此,在大多数情况下,您还应该添加经过身份验证的操作。
基本经过身份验证的 Admin-Ajax 示例
如果要提供仅限经过身份验证的用户使用的数据,则需要注册一个wp_ajax_{action}
操作处理程序。未经身份验证的请求会收到一个0
字符串响应。
<?php
namespace PublicFunctionOrg\WordPress\CodeSamples;
// ------------------------------------------------
// /wp-admin/admin-ajax.php?action=my_action
// ------------------------------------------------
function my_authorized_action_handler(){
wp_send_json([
"firstname" => wp_get_current_user()->first_name,
"lastname" => wp_get_current_user()->last_name,
]);
exit;
}
add_action('wp_ajax_my_action',__NAMESPACE__.'\my_authorized_action_handler');
Admin-Ajax 方法实现起来非常简单,但不适合构建大型 api。
WP_REST
WP_REST 1.0 随 WordPress 4.4 版一起提供。当 Gutenberg 与 WordPress 5.0 一起发布时,后端的事情变得更加异步。需要一种更结构化的方式来实现 Ajax 调用,所以升级到了 WP_REST 2.0。
基本未经身份验证的 WP_REST 示例
使用该rest_api_init
操作来注册您自己的 api 端点。您可以使用该register_rest_route
功能注册新路线。
<?php
namespace PublicFunctionOrg\WordPress\CodeSamples;
// ------------------------------------------------
// GET /wp-json/code-samples/v1/basic
// ------------------------------------------------
add_action( 'rest_api_init', function () {
register_rest_route(
"code-samples/v1",
"/basic",
[
'methods' => \WP_REST_Server::READABLE,
'permission_callback' => '__return_true',
'callback' => function (\WP_REST_Request $request) {
return array_map( function ( $post ) {
return $post->post_title;
}, get_posts() );
},
]
);
} );
我们现在可以使用 URL 调用我们的 Ajax 路由/wp-json/code-samples/v1/basic
。
第一个参数是命名空间,它通常由插件的 slug
或描述内容的慢字符串和版本字符串组成。第二个参数是这个命名空间内的路由。
第三个参数是一个配置数组。该methods
参数允许您选择此路由将接受的请求方法。通常,每个路由只允许一个方法,但您也可以指定多个方法作为逗号分隔的列表或方法数组。有效方法字符串的常量可以在 WP_REST_Server
类中找到。如果没有明确指定方法,则使用GET
。
您还必须定义一个permission_callback
. 由于我们的路由接受任何 GET 请求,我们可以使用一个名为的核心函数__return_true
,该函数通过始终返回 true
来授予继续处理所有请求的权限。
最后但并非最不重要的callback
论点。它需要一些可调用的值来返回响应数据。响应格式为 JSON。
基本经过身份验证的 WP_REST 示例
除了permission_callback
参数之外,它与未经身份验证的代码示例几乎相同。
<?php
namespace PublicFunctionOrg\WordPress\CodeSamples;
// ------------------------------------------------
// GET /wp-json/code-samples/v1/basic
// ------------------------------------------------
add_action( 'rest_api_init', function () {
register_rest_route(
"code-samples/v1",
"/basic",
[
'methods' => \WP_REST_Server::READABLE,
'permission_callback' => function (\WP_REST_Request $request) {
return is_user_logged_in();
},
'callback' => function (\WP_REST_Request $request) {
return [
"firstname" => wp_get_current_user()->first_name,
"lastname" => wp_get_current_user()->last_name,
];
},
]
);
} );
此端点仅接受授权请求,因为我们使用该is_user_logged_in()
函数检查登录状态。但是,如果您在浏览器中具有有效的登录会话并调用此 url,您将收到未经授权的错误响应。这是因为 WP_REST api 使用 nonce 令牌进行授权检查。您可以使用@wordpress/api-fetch包,如果您登录,它会自动处理 nonce 令牌。
Ajax 端点仍然相当容易实现,但您必须指定名称空间、请求方法和权限处理,这将有助于您处理更大的项目。
重写规则
添加重写规则是这三种变体中最复杂的。我们需要使用两个动作和一个过滤器来使其工作。
<?php
namespace PublicFunctionOrg\WordPress\CodeSamples;
// ------------------------------------------------
// /my/custom/route
// ------------------------------------------------
add_filter( 'query_vars', function( $vars ) {
$vars[] = "my_route";
return $vars;
});
add_action( 'init', function(){
add_rewrite_rule( '^my/custom/route/?', 'index.php?my_route=1' );
});
add_action( 'parse_request', function(){
if ( isset( $wp->query_vars[ "my_route"] ) &&
"1" === $wp->query_vars[ "my_route"]
) {
$latestPostTitles = array_map(function($post){
return $post->post_title;
}, get_posts());
wp_send_json($latestPostTitles);
exit;
}
});
首先,我们需要添加一个查询变量,以便我们可以识别我们的 Ajax 请求。其次,我们向系统添加自定义重写规则并将其映射到我们的查询变量。在最后一步,我们拦截请求解析器并检查我们的变量是否存在。如果是,我们可以假设我们的路由已被调用并提供响应。
建议
仅在具有一两个非常简单的端点的非常简单的情况下才使用 Admin-Ajax。
在我看来,WP_REST 是大多数情况下的方法。它迫使您考虑为路由命名空间和处理权限,并具有更多用于验证和清理请求变量的好功能。您可以设计适当的 RESTful 实体,但也可以将其用于简单的 Ajax 路由。
仅当您有 Admin-Ajax 或 WP_REST 无法满足的严格 URL 路径或响应格式要求时,才回退到重写规则变体。
注:本文出自 medium.com,作者为Edward Bock,由 WordPress大学 翻译整理。
推荐阅读:
- 使用这些 WordPress 插件扩展 REST API
- 使用REST API TO MiniProgram插件快速为WordPress网站生成小程序
- 使用WordPress REST API创建WordPress设置页面
- 禁用 WordPress 的 JSON REST API
- WordPress:自定义WP REST API (WP API)授权
我曾写过对WordPress两种AJAX的方法的对比,并且有对比代码清晰分析。实际上就是本文的方法一和方法三
https://blog.brain1981.com/2078.html
方法二即WP的自带Rest API其实我不太喜欢用,因为每个网站都有,可能涉及安全问题并且不如自己写的接口用起来自由。
不明觉厉……