WordPress Ajax 端点实现的 3 个变体

文章目录[隐藏]

至少有三种方法可以在 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大学 翻译整理。

推荐阅读:

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
欢迎关注我们的微信公众号:WPDAXUE

倡萌

一个文科IT宅男,喜欢折腾WordPress和被它折腾 ^_^

1 条评论

发表评论

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