在本系列的上一篇文章中,我们重新讨论了在WordPress中使用Ajax的主题。 最终,目标是改进几年前在该站点上运行的以前的系列 。
重申一下,并不是说原始系列中讲授的技术是错误的,而是软件会随着时间的推移而变化,因此最好回顾一下几年前介绍的概念,并尝试将其更新为更具最新性和灵活性的东西。为我们的发展努力。
回想一下以前的帖子 ,我们看了原始系列的以下评论:
我们将简要介绍一下Ajax是什么,它如何工作,如何在前端进行设置以及了解WordPress提供的功能。 实际上,我们还将构建一个将理论付诸实践的小项目。 我们将遍历源代码,并确保它在GitHub上也可用。
在那篇文章中,我们回顾了一些使用过程编程将WordPress Ajax API集成到我们的项目中的高级方法。 在本文中,我们将采用在本系列第一部分中编写的代码并对其进行重构,以使其使用面向对象的方法。
最终,目的不是要弄清楚为什么一个范式应该在另一个范式上使用; 相反,这是为了展示我们如何能够实现相同的功能,而与构建插件时选择的方法无关。
规划插件
在开始重构代码之前,我们需要考虑的是如何布置各种文件。 毕竟,开始一个新项目,甚至跳入一个老项目的过程的一部分,是计划如何完成工作。
对于这个特定的插件,我们将需要以下内容:
- 一个引导文件,负责初始化主类并启动插件
- 一个负责加载依赖项的类,例如JavaScript
- 用作主插件类的类
如您所见,我们对该插件没有太多要做。 我们还将重新组织一些文件,使其具有一致的目录结构,并确保正确记录所有代码,使其遵循WordPress编码标准 。
话虽如此,让我们开始吧。
整理文件
在编写任何代码之前,让我们继续执行以下操作:
- 创建
assets
目录。 - 创建一个将位于
assets
目录中的js
目录。 - 将
frontend.js
移到js
目录。
这样做的原因是我们正在进入一种面向对象的编程风格。 其中一部分包括组织文件,使它们遵循通常被视为软件包的约定。
在我们的例子中, assets
目录包含了使程序运行所需的所有东西。 对于某些插件,这可能是JavaScript,CSS,图像,字体等。 在这种情况下,我们只有一个JavaScript文件。
依赖加载器
接下来,我们需要引入一个类,该类负责为我们的项目加载依赖项。 对于这个特定的插件,我们唯一的依赖关系就是我们刚刚放置在assets
目录中JavaScript文件。
面向对象编程的一部分是确保每个类都有特定的目的。 在这种情况下,我们将要介绍的类将负责使用WordPress API加载JavaScript。
让我们从创建类的基本结构开始:
<?php
/**
* Loads and enqueues dependencies for the plugin.
*
* @since 1.0.0
*
* @package WPA/includes
*/
class Dependency_Loader {
}
接下来,我们将添加一个方法,该方法将负责按照WordPress API排队JavaScript。
<?php
/**
* Loads and registers dependencies.
*
* @since 1.0.0
*
* @package WPA
* @author Tom McFarlin
* @license http://www.gnu.org/licenses/gpl-2.0.txt
* @link https://tommcfarlin.com/
*/
/**
* Loads and enqueues dependencies for the plugin.
*
* @package WPA
* @subpackage WPA/includes
* @since 1.0.0
* @author Tom McFarlin
* @license http://www.gnu.org/licenses/gpl-2.0.txt
* @link https://tommcfarlin.com/
*/
class Dependency_Loader {
/**
* Initializes the plugin by enqueuing the necessary dependencies.
*
* @since 1.0.0
*/
public function initialize() {
$this->enqueue_scripts();
}
/**
* Enqueues the front-end scripts for getting the current user's information
* via Ajax.
*
* @access private
*
* @since 1.0.0
*/
private function enqueue_scripts() {
wp_enqueue_script(
'ajax-script',
plugin_dir_url( dirname( __FILE__ ) ) . 'assets/js/frontend.js',
array( 'jquery' )
);
wp_localize_script(
'ajax-script',
'sa_demo',
array( 'ajax_url' => admin_url( 'admin-ajax.php' ) )
);
}
}
之后,我们需要采用负责处理Ajax请求和提供响应的功能,然后将它们添加到类中。 由于它们将在类的上下文中,因此我们需要添加一个新功能,以在WordPress中进行注册。
我们将创建一个setup_ajax_handlers
函数。 看起来像这样:
<?php
/**
* Registers the callback functions responsible for providing a response
* to Ajax requests setup throughout the rest of the plugin.
*
* @since 1.0.0
*/
public function setup_ajax_handlers() {
add_action(
'wp_ajax_get_current_user_info',
array( $this, 'get_current_user_info' )
);
add_action(
'wp_ajax_nopriv_get_current_user_info',
array( $this, 'get_current_user_info' )
);
}
接下来,我们需要将函数实际移入此类。 请注意,原来以_sa
的功能不再标记为。 由于它们在类的上下文中,因此我们可以删除前缀,也可以删除下划线以使用private
关键字。
<?php
public function get_current_user_info() {
$user_id = get_current_user_id();
if ( $this->user_is_logged_in( $user_id ) && $this->user_exists( $user_id ) ) {
wp_send_json_success(
wp_json_encode( get_user_by( 'id', $user_id ) )
);
}
}
private function user_is_logged_in( $user_id ) {
$is_logged_in = true;
if ( 0 === $user_id ) {
wp_send_json_error(
new WP_Error( '-2', 'The visitor is not currently logged into the site.' )
);
$is_logged_in = false;
}
return $is_logged_in;
}
private function user_exists( $user_id ) {
$user_exists = true;
if ( false === get_user_by( 'id', $user_id ) ) {
wp_send_json_error(
new WP_Error( '-1', 'No user was found with the specified ID [' . $user_id . ']' )
);
$user_exists = false;
}
return $user_exists;
}
然后,我们将该文件保存在插件目录根目录中的includes
目录中。 includes
目录通常是整个项目中使用的代码所在的位置。 关于这个特定的目录可以说更多,但这是更长篇幅的内容。
该类的最终版本应如下所示:
<?php
/**
* Loads and registers dependencies.
*
* @since 1.0.0
*
* @package WPA
* @author Tom McFarlin
* @license http://www.gnu.org/licenses/gpl-2.0.txt
* @link https://tommcfarlin.com/
*/
/**
* Loads and enqueues dependencies for the plugin.
*
* @package WPA
* @subpackage WPA/includes
* @since 1.0.0
* @author Tom McFarlin
* @license http://www.gnu.org/licenses/gpl-2.0.txt
* @link https://tommcfarlin.com/
*/
class Dependency_Loader {
/**
* Initializes the plugin by enqueuing the necessary dependencies.
*
* @since 1.0.0
*/
public function initialize() {
$this->enqueue_scripts();
}
/**
* Enqueues the front-end scripts for getting the current user's information
* via Ajax.
*
* @access private
*
* @since 1.0.0
*/
private function enqueue_scripts() {
wp_enqueue_script(
'ajax-script',
plugin_dir_url( dirname( __FILE__ ) ) . 'assets/js/frontend.js',
array( 'jquery' )
);
wp_localize_script(
'ajax-script',
'sa_demo',
array( 'ajax_url' => admin_url( 'admin-ajax.php' ) )
);
}
/**
* Registers the callback functions responsible for providing a response
* to Ajax requests setup throughout the rest of the plugin.
*
* @since 1.0.0
*/
public function setup_ajax_handlers() {
add_action(
'wp_ajax_get_current_user_info',
array( $this, 'get_current_user_info' )
);
add_action(
'wp_ajax_nopriv_get_current_user_info',
array( $this, '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
*/
public function get_current_user_info() {
$user_id = get_current_user_id();
if ( $this->user_is_logged_in( $user_id ) && $this->user_exists( $user_id ) ) {
wp_send_json_success(
wp_json_encode( get_user_by( 'id', $user_id ) )
);
}
}
/**
* 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.
*
* @return bool $is_logged_in Whether or not the current user is logged in.
*/
private function user_is_logged_in( $user_id ) {
$is_logged_in = true;
if ( 0 === $user_id ) {
wp_send_json_error(
new WP_Error( '-2', 'The visitor is not currently logged into the site.' )
);
$is_logged_in = false;
}
return $is_logged_in;
}
/**
* Determines if a user with the specified ID exists in the WordPress database. If not, then will
* the following error code and message will be returned to the client:
*
* -1: No user was found with the specified ID [ $user_id ].
*
* @access private
* @since 1.0.0
*
* @param int $user_id The current user's ID.
*
* @return bool $user_exists Whether or not the specified user exists.
*/
private function user_exists( $user_id ) {
$user_exists = true;
if ( false === get_user_by( 'id', $user_id ) ) {
wp_send_json_error(
new WP_Error( '-1', 'No user was found with the specified ID [' . $user_id . ']' )
);
$user_exists = false;
}
return $user_exists;
}
}
主班
现在,我们准备为插件编写主类。 这个特定的类将位于plugin目录的根目录中,并且该类的基本结构如下所示:
<?php
/**
* Loads and enqueues dependencies for the plugin.
*
* @since 1.0.0
*
* @package Acme
*/
class Acme_Simple_Ajax {
}
接下来,我们将添加几个在实例化该类时要设置的属性:
<?php
class Acme_Simple_Ajax {
private $version;
private $loader;
}
之后,我们将创建一个构造函数和一个初始化函数,这些函数将用于使插件运行:
<?php
/**
* The primary class for the plugin
*
* Stores the plugin version, loads and enqueues dependencies
* for the plugin.
*
* @since 1.0.0
*
* @package Acme
* @author Tom McFarlin
* @license http://www.gnu.org/licenses/gpl-2.0.txt
* @link https://tommcfarlin.com/
*/
/**
* Stores the plugin version, loads and enqueues dependencies
* for the plugin.
*
* @package Acme
* @author Tom McFarlin
* @license http://www.gnu.org/licenses/gpl-2.0.txt
* @link https://tommcfarlin.com/
*/
class Acme_Simple_Ajax {
/**
* Represents the current version of this plugin.
*
* @access private
* @since 1.0.0
* @var string
*/
private $version;
/**
* A reference to the Dependency Loader.
*
* @access private
* @since 1.0.0
* @var Dependency_Loader
*/
private $loader;
/**
* Initializes the properties of the class.
*
* @access private
* @since 1.0.0
*/
public function __construct() {
$this->version = '1.0.0';
$this->loader = new Dependency_Loader();
}
/**
* Initializes this plugin and the dependency loader to include
* the JavaScript necessary for the plugin to function.
*
* @access private
* @since 1.0.0
*/
public function initialize() {
$this->loader->initialize();
$this->loader->setup_ajax_handlers();
}
}
在上面的代码中,构造函数设置属性并实例化使插件运动所需的依赖关系。
调用initialize
,插件将启动,并且它将在我们在本教程前面创建的依赖项类上调用initialize方法。
引导程序
我们需要做的最后一件事是获取拥有的主文件,使用PHP的include
功能,并确保它知道我们拥有的必要PHP文件。
<?php
/**
* Loads and registers dependencies.
*/
include_once( 'includes/class-dependency-loader.php' );
/**
* The primary class for the plugin
*/
include_once( 'class-acme-simple-ajax.php' );
之后,我们需要定义一个方法,该方法将初始化主插件文件并设置所有内容。
<?php
/**
* Instantiates the main class and initializes the plugin.
*/
function acme_start_plugin() {
$plugin = new Acme_Simple_Ajax();
$plugin->initialize();
}
引导程序文件的最终版本应如下所示:
<?php
/**
* This plugin demonstrates how to use the WordPress Ajax APIs.
*
* @package Acme
*
* @wordpress-plugin
* 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
*/
// If this file is called directly, abort.
if ( ! defined( 'WPINC' ) ) {
die;
}
/**
* Loads and registers dependencies.
*/
include_once( 'includes/class-dependency-loader.php' );
/**
* The primary class for the plugin
*/
include_once( 'class-acme-simple-ajax.php' );
/**
* Instantiates the main class and initializes the plugin.
*/
function acme_start_plugin() {
$plugin = new Acme_Simple_Ajax();
$plugin->initialize();
}
acme_start_plugin();
首先,通过检查是否已定义WordPress常量来检查文件是否直接访问。 如果不是,则执行停止。
之后,它包括我们通过本教程创建的各种类。 最后,它定义了一个功能,当WordPress加载该插件时该函数将启动该插件并将所有内容设置为动态。
结论
至此,本系列分为两部分。 希望您不仅学到了将Ajax集成到WordPress项目中的一些最佳实践,而且还学到了有关记录过程性代码和面向对象的代码的知识,以及了解布局多少代码的区别。
在以后的文章中,我可能会回顾这里介绍的一些面向对象的概念,并详细介绍它们。 但是,现在,使用此页面侧边栏上的GitHub链接查看插件。
记住,您可以在我的个人资料页面上捕获我的所有课程和教程,还可以在@tommcfarlin 上的博客和/或Twitter上关注我,在其中我谈论了WordPress上下文中的软件开发。
与往常一样,请不要在下面的提要中留下任何问题或评论,我将尽力回答每个问题或评论。