几年前,我写了一系列文章,讨论如何在WordPress Frontend中使用Ajax 。 该系列的目的很简单:
我们将简要介绍一下Ajax是什么,它如何工作,如何在前端进行设置以及了解WordPress提供的功能。 实际上,我们还将构建一个将理论付诸实践的小项目。 我们将遍历源代码,并确保它在GitHub上也可用。
总体而言,该系列很好,但正如不断开发的所有软件一样,技术,API和方法也在不断变化。 此外,随着时间的流逝,我们将继续提高自己的技能,我们在开发方面会变得更好,在使用新的API方面也会变得更好。
由于上述所有原因,我想重新审视WordPress中的Ajax概念,以便您看到一些新的API,以及如何在日常工作中使用它们或如何重构您可能正在使用的某些代码。现在。
在深入学习本教程之前,请注意:我假设您已经阅读了本文简介中链接的系列文章,并且您已经拥有构建WordPress插件的经验。
定义插件
与任何WordPress插件一样,确保定义标头非常重要,以便WordPress能够读取文件,以便将新功能引入核心应用程序。
我称之为插件Simple Ajax Demo的这种变体,它位于wp-content/plugin/wp-simple-ajax
。 我创建的第一个文件位于wp-simple-ajax
的根目录中,称为wp-simple-ajax.php
。
看起来像这样:
<?php
/**
* Plugin Name: Simple Ajax Demo
* Description: A simple demonstration of the WordPress Ajax APIs.
* Version: 1.0.0
* Author: Tom McFarlin
* Author URI: https://tommcfarlin.com/
* License: GPL-2.0+
* License URI: http://www.gnu.org/licenses/gpl-2.0.txt
*/
该代码应该是不言自明的,特别是如果您习惯使用WordPress插件; 但是,最重要的是要了解的是,以上所有信息将推动用户在WordPress仪表板中看到的内容。
也就是说,当用户看到激活插件的选项时,他们会看到插件的名称,描述和版本以及作者的名字(将链接到指定的URL)。
添加WordPress的Ajax文件
此时,该插件将显示在WordPress插件仪表板中,但实际上不会执行任何操作,因为我们尚未编写任何代码。 为了实现这一点,我们将使用过程编程方法而不是我在大多数教程中使用的面向对象方法来处理此特定插件。
我们最初如何添加Ajax支持
现在避免使用面向对象编程的原因有两个:
- 这是因为该插件将非常简单。 我对专注于WordPress提供的指定API更加感兴趣,因此您可以专注于工作中最重要的事情。
- 本系列的第二部分将重点讨论将代码重构为面向对象的系统,以便您可以在使用类的大型系统的上下文中看到所有这些内容。
最终,本系列文章将涵盖PHP和WordPress支持的两种编程类型。
最有可能的是,如果您过去使用过Ajax,那么您已经做了类似的事情,以便为您的插件提供支持进行异步调用的功能:
<?php
add_action( 'wp_head','acme_add_ajax_support' );
function acme_add_ajax_support() {
?>
<script type="text/javascript">
var ajaxurl = '<?php echo admin_url( 'admin-ajax.php' ); ?>';
</script>
<?php
}
这种特定的方法并不是天生的错误,但是它确实忽略了我稍后将介绍的一些较新的API。 它还将PHP,HTML和JavaScript混合在一个函数中。
它不能很好地完成工作,但是有一种更干净的方法可以做到这一点。
我们如何添加Ajax支持
首先,为确保任何人都不能直接访问该插件,请在插件的标题下方添加以下条件:
<?php
// If this file is called directly, abort.
if ( ! defined( 'WPINC' ) ) {
die;
}
请注意,由于此代码将在以后的预先存在的PHP文件中提供(对于语法高亮显示现在是必需的),因此不需要打开PHP标签。
接下来,让我们通过使用一些不涉及混合语言的现有API来设置一个功能,以包括WordPress对Ajax的支持。
这是我们需要做的:
- 我们将创建一个负责添加Ajax支持的函数。
- 我们将把函数挂接到
wp_enqueue_script
动作中。 - 我们将利用
wp_localize_script
API调用,以使WordPress对Ajax的支持(来自admin-ajax.php
)。
看起来很简单,不是吗? 请注意,如果您有任何问题,可以随时将其添加到注释中。 查看以下代码,看看是否可以遵循:
<?php
add_action( 'wp_enqueue_scripts', 'sa_add_ajax_support' );
/**
* Adds support for WordPress to handle asynchronous requests on both the front-end
* and the back-end of the website.
*
* @since 1.0.0
*/
function sa_add_ajax_support() {
wp_localize_script(
'ajax-script',
'sa_demo',
array(
'ajaxurl' => admin_url( 'admin-ajax.php' )
)
);
}
同样,请注意,在插件的最终版本中不需要打开PHP标签,因为此处仅是为了利用语法突出显示功能。
话虽如此,看看wp_localize_script
。 在检查每个参数之前,让我们回顾一下此功能的用途。 从Codex出发 ,简短版本如下:
使用JavaScript变量的数据对注册的脚本进行本地化。
不过,较长的描述很重要:
这样,您就可以为脚本中使用的所有字符串提供正确的本地化翻译。 这是必要的,因为WordPress当前仅提供PHP中的本地化API,而不直接提供JavaScript中的本地化API。
尽管本地化是主要用途,但是它可以用于使脚本可用的任何数据通常只能从WordPress的服务器端获取。
现在查看它接受的参数:
- 第一个参数称为
handle
,用于唯一地标识要添加到页面的脚本。 - 第二个参数是
name
,这很重要,因为这是在整个代码中标识脚本的方式。 您将在本教程的后面部分更详细地了解这一点。 - 第三个参数是
data
参数。 它是指将作为JavaScript对象发送到浏览器的数组。 由于我们将路径的URL传递到文件,因此将提供Ajax支持。
注意第一个参数是ajax-script
。 当我们将注意力转移到编写和排队我们自己JavaScript时,请记住这一点,因为我们需要再使用一次该句柄。
还要记住记下您为调用API选择的名称,因为在本教程后面的客户端代码中,我们将使用该名称。
关于Ajax支持的重要说明
注意,我们仅使用wp_enqueue_script
钩子,而未使用admin_enqueue_script
。 这是因为ajaxurl
已在仪表板中定义。
这意味着,如果您希望在WordPress的管理区域中提出Ajax请求,则无需排队。 在本教程中,我们正在做的所有事情都是专门针对网站的前端的。
设置服务器端代码
现在是时候编写您JavaScript通过Ajax调用的函数了。 这可以是您想要的任何东西,但是出于此插件的目的,我们将设置一个函数,该函数将返回有关登录到该站点的用户的信息。
该插件将执行以下操作:
- 向服务器发出请求,以获取有关当前用户的信息。
- 如果用户登录到该站点,它将返回该用户信息的JSON响应。
- 如果用户未登录,则将返回错误代码。
我们将使用大多数现代浏览器中可用的console
对象,因此请确保在使用将要编写JavaScript源时使用的是Chrome,Safari或Firefox。
发出请求
现在,我们已经精确地概述了每当用户向服务器发出Ajax请求时代码将如何工作,让我们开始编写一个函数来实现此目的。 我们将其称为sa_get_user_information
。
<?php
add_action( 'wp_ajax_get_current_user_info', 'sa_get_current_user_info' );
add_action( 'wp_ajax_nopriv_get_current_user_info', 'sa_get_current_user_info' );
/**
* Retrieves information about the user who is currently logged into the site.
*
* This function is intended to be called via the client-side of the public-facing
* side of the site.
*
* @since 1.0.0
*/
function sa_get_current_user_info() {
}
该函数的实现将在本教程的后面部分介绍,但是上面代码的主要wp_ajax_get_current_user_info
是,我们已经将wp_ajax_get_current_user_info
和wp_ajax_nopriv_get_current_user_info
都wp_ajax_nopriv_get_current_user_info
。
这两个挂钩在Codex中有详细记录,但是第一个挂钩将允许那些登录到站点的人访问此功能。 在第二挂钩将使那些还没有登录到这个网站谁访问此功能。
还请注意,作为开发人员, wp_ajax_
和wp_ajax_nopriv_
之后的所有事情wp_ajax_
您决定。 这将是您从客户端调用的函数的名称,您将在本教程的后面看到。
处理错误的请求
在实现该功能之前,已调用JavaScript源文件(尚未编写),并且我们需要确保能够处理可能发生的任何错误。
在我们的情况下,潜在的错误可能是:
- 没有人登录。
- 用户标识在系统中不存在。
第二种情况极不可能实现,但这将帮助我们更多地了解更多WordPress API,以及如何利用它们来处理错误请求。
首先要了解的是WP_Error
。 与许多API一样,可以在Codex中使用 :
WP_Error的实例存储错误代码和表示一个或多个错误的消息,并且可以使用is_wp_error()函数确定变量是否为WP_Error的实例。
构造函数最多可以接受三个参数(尽管我们只会使用前两个参数):
- 第一个参数是错误代码。 这就是我们可以在客户端使用的解析和确定出了什么问题的方法。 它还允许我们将信息写入日志文件,等等。
- 第二个参数是一条消息,它可以伴随错误代码。 如果我们想向用户显示消息,这很有用。
- 最后一个参数是一组信息,通常是错误代码和消息。 无论如何,我们不会在代码中使用它。
接下来,我们将使用名为wp_send_json_error
的函数将错误的结果发送回客户端。 这真的很容易使用 :
将JSON响应发送回Ajax请求,指示失败。 响应对象将始终具有值为false的成功密钥。 如果$ data参数中的任何内容传递给该函数,它将被编码为数据键的值。
通过结合WP_Error
和wp_send_json_error
,我们可以创建函数,以帮助我们向调用服务器端JavaScript提供错误代码。
例如,假设我们有一个功能,如果用户未登录到网站,则会提供错误消息。 这可以通过以下功能实现:
<?php
/**
* Determines if a user is logged into the site using the specified user ID. If not,
* then the following error code and message will be returned to the client:
*
* -2: The visitor is not currently logged into the site.
*
* @access private
* @since 1.0.0
*
* @param int $user_id The current user's ID.
*/
function _sa_user_is_logged_in( $user_id ) {
if ( 0 === $user_id ) {
wp_send_json_error(
new WP_Error( '-2', 'The visitor is not currently logged into the site.' )
);
}
}
请注意,即使该函数位于全局名称空间中,它也被标记为私有。 它带有下划线前缀,以表示该功能应被视为私有。
我们将在下一篇文章中重新讨论。
其次,如果用户不存在,我们需要处理该情况。 为此,我们可以创建一个执行以下操作的函数:
<?php
/**
* Determines if a user is logged into the site using the specified user ID. If not,
* then the following error code and message will be returned to the client:
*
* -3: The visitor does not have an account
*
* @access private
* @since 1.0.0
*
* @param int $user_id The current user's ID.
*/
function _sa_user_exists( $user_id ) {
if ( 0 === $user_id ) {
wp_send_json_error(
new WP_Error( '-3', 'The visitor does not have an account with this site.' );
);
}
}
现在,我们有两个功能,如果发生故障,每个功能都会将信息发送回客户端,但是如果这两个功能都通过了,我们该怎么办?
处理成功的请求
如果上面的函数没有产生任何错误,那么我们需要一种方法,将一条成功的消息及其请求的信息发送回客户端。
也就是说,我们需要将包含当前用户信息(以JSON格式)的信息发送回客户端。
为此,我们可以利用wp_send_json_success
消息。 它也完全按照您的想法去做:
将JSON响应发送回Ajax请求,指示成功。 响应对象将始终具有值为true的成功密钥。 如果将任何内容传递给该函数,它将被编码为数据键的值。
让我们结合到目前为止已经完成的工作来编写一个JavaScript最终将调用的函数,该函数利用了上面放置的两个较小的函数。 实际上,这将是我们在本教程前面忽略的功能的实现:
<?php
add_action( 'wp_ajax_get_current_user_info', 'sa_get_current_user_info' );
add_action( 'wp_ajax_nopriv_get_current_user_info', 'sa_get_current_user_info' );
/**
* Retrieves information about the user who is currently logged into the site.
*
* This function is intended to be called via the client-side of the public-facing
* side of the site.
*
* @since 1.0.0
*/
function sa_get_current_user_info() {
// Grab the current user's ID
$user_id = get_current_user_id();
// If the user is logged in and the user exists, return success with the user JSON
if ( _sa_user_is_logged_in( $user_id ) && _sa_user_exists( $user_id ) ) {
wp_send_json_success(
json_encode( get_user_by( 'id', $user_id ) )
);
}
}
如果用户已登录并且该用户存在,那么我们将向客户端发送一条成功消息,其中包含用户的JSON表示形式。 现在,该写一些JavaScript了。
客户端请求
首先,将一个名为frontend.js
的文件添加到插件目录的根目录。 最初,它应包含以下代码:
;(function( $ ) {
'use strict';
$(function() {
});
})( jQuery );
该函数的实现将暂时涉及,但是我们需要确保也在插件中将此JavaScript文件加入队列。 返回到函数sa_add_ajax_support
,并将以下内容添加到wp_localize_script
的调用wp_localize_script
:
<?php
wp_enqueue_script(
'ajax-script',
plugin_dir_url( __FILE__ ) . 'frontend.js',
array( 'jquery' )
);
请记住,此脚本必须具有与wp_localize_script
定义的脚本相同的句柄。 现在,我们可以重新访问我们JavaScript文件,并调用整篇文章中我们一直在努力的服务器端代码。
在frontend.js
,添加以下代码:
/**
* This file is responsible for setting up the Ajax request each time
* a WordPress page is loaded. The page could be the main index page,
* a single page, or any other type of information that WordPress renders.
*
* Once the DOM is ready, it will make an Ajax call to the server where
* the `get_current_user_info` function is defined and will then handle the
* response based on the information returned from the request.
*
* @since 1.0.0
*/
;(function( $ ) {
'use strict';
$(function() {
/* Make an Ajax call via a GET request to the URL specified in the
* wp_enqueue_script call. For the data parameter, pass an object with
* the action name of the function we defined to return the user info.
*/
$.ajax({
url: sa_demo.ajax_url,
method: 'GET',
data: { action: 'get_current_user_info' }
}).done(function( response ) {
/* Once the request is done, determine if it was successful or not.
* If so, parse the JSON and then render it to the console. Otherwise,
* display the content of the failed request to the console.
*/
if ( true === response.success ) {
console.log( JSON.parse( response.data ) );
} else {
console.log( response.data );
}
});
});
})( jQuery );
考虑到代码中的注释数量,并且假设您熟悉编写WordPress插件并具有Ajax的使用经验,则应该相对容易地遵循它。
简而言之,当页面加载时,上面的代码会调用服务器端,然后将有关当前用户的信息写入浏览器的控制台。
如果用户已登录,则该信息将以JavaScript对象的形式写到控制台,因为它是通过JSON解析的。
如果,另一方面,用户没有登录,则其他对象将写出显示与消息,所有这一切,你将能够在控制台看到沿着错误代码。
结论
到目前为止,您应该对WordPress可以用于登录站点的用户和未登录站点的用户处理Ajax请求的API有清晰的了解。
最终,我们的目标应该是编写最干净,最可维护的代码,以便我们有能力在将来迈向继续使用该代码。 此外,我们应该像这样编写代码,以便其他可能接触我们代码库的人对我们正在尝试做的事情有清楚的了解,并在给定环境的情况下使用最佳实践。
在本教程中,我对通过GitHub共享,演示和提供的所有代码使用了程序化的编程形式。 如前所述,这没有内在的错误,但是我确实值得从面向对象的角度看这是什么样子。
在下一个教程中,我们将着眼于将此代码重构为一个面向对象的范例,该范例也使用WordPress编码标准来进一步记录我们的工作,并使用清晰的文件组织使我们的文字尽可能清晰。
记住,您可以在我的个人资料页面上捕获我的所有课程和教程,还可以在@tommcfarlin 上的博客和/或Twitter上关注我,在其中我谈论WordPress上下文中的软件开发,并喜欢与他人讨论相同的问题。主题(以及其他内容)。
在此期间,请不要在下面的Feed中留下任何问题或评论,我将尽力回答每个问题或评论。