() translation by (you can also view the original English article)
В предыдущем посте в этой серии мы пересматривали тему работы с Ajax в WordPress. В конечном счете, цель состоит в том, чтобы улучшить предыдущую серию, которая была запущена на сайте несколько лет назад.
Повторяю, это не значит, что методы, описанные в оригинальной серии, были ошибочными, но со временем программное обеспечение меняется, поэтому всегда полезно пересмотреть концепции, которые были рассмотрены много лет назад, и попытаться обновить их.
Вспомните предыдущий пост, где мы обратили внимание на следующий комментарий из оригинальной серии:
Мы собираемся сделать очень краткий обзор того, что такое Ajax, как он работает, как настроить его на передней панели и понять, какие ловушки поддерживает WordPress. Мы также создадим небольшой проект, который воплотит эту теорию в жизнь. Мы просмотрим исходный код, и мы также убедимся, что он доступен и на GitHub.
И в этой статье мы рассмотрели некоторые дополнительные способы включения API Ajax для WordPress в наши проекты с использованием процедурного программирования. В этом посте мы собираемся взять код, который мы написали в первой части этой серии, и реорганизовать его так, чтобы он использовал объектно-ориентированный подход.
В конечном счете, цель состоит не в том, чтобы привести пример, когда одна парадигма должна использоваться вместо другой; Вместо этого мы должны показать, как мы можем достичь той же функциональности независимо от подхода, который вы выбираете при создании своих плагинов.
Планирование плагина
Прежде чем мы начнем рефакторинг кода, мы должны рассмотреть, как мы собираемся выкладывать различные файлы. В конце концов, часть процесса создания нового проекта - или даже прыжка в старый - планирование того, как будет все будет работать.
Для этого конкретного плагина нам понадобятся следующие:
- Файл bootstrap, который отвечает за инициализацию основного класса и запуск плагина
- Класс, отвечающий за загрузку зависимостей, таких как JavaScript
- Класс, который является основным классом плагинов
Как вы можете видеть, нам не так уж много нужно делать. Мы также будем реорганизовывать некоторые файлы, чтобы иметь согласованную структуру каталогов, а так же будем обязательно будем документировать весь код так, чтобы он соответствовал стандартам кодирования WordPress.
С учетом всего вышесказанного, давайте начнем.
Организация файлов
Прежде чем мы начнем писать любой код, давайте сделаем следующее:
- Создайте каталог
assets
. - Создайте каталог
js
, который будет находиться в каталогеassets
. - Перенесите
frontend.js
в каталогjs
.



Причина этого в том, что мы переходим к объектно-ориентированному стилю программирования. Часть этого включает в себя организацию наших файлов, чтобы они следовали соглашениям, которые часто считаются пакетами.
В нашем случае каталог assets
включает в себя все необходимое для запуска программы. Для некоторых плагинов это могут быть JavaScript, CSS, изображения, шрифты и т. Д. В этом случае у нас есть один файл JavaScript.
Загрузчик зависимостей
Далее нам нужно ввести класс, который будет отвечать за загрузку зависимостей для нашего проекта. Для этого конкретного плагина единственная зависимость, которая у нас есть, это файл JavaScript, который мы только что разместили в каталоге assets
.
Часть объектно-ориентированного программирования гарантирует, что каждый класс имеет конкретную цель. В этом случае класс, который мы собираемся ввести, будет отвечать за загрузку JavaScript с использованием WordPress API.
Начнем с создания базовой структуры класса:
1 |
<?php
|
2 |
|
3 |
/**
|
4 |
* Loads and enqueues dependencies for the plugin.
|
5 |
*
|
6 |
* @since 1.0.0
|
7 |
*
|
8 |
* @package WPA/includes
|
9 |
*/
|
10 |
class Dependency_Loader { |
11 |
|
12 |
}
|
Затем мы добавим метод, который будет отвечать за загрузку JavaScript в соответствии с API WordPress.
1 |
<?php
|
2 |
/**
|
3 |
* Loads and registers dependencies.
|
4 |
*
|
5 |
* @since 1.0.0
|
6 |
*
|
7 |
* @package WPA
|
8 |
* @author Tom McFarlin
|
9 |
* @license https://www.gnu.org/licenses/gpl-2.0.txt
|
10 |
* @link https://tommcfarlin.com/
|
11 |
*/
|
12 |
|
13 |
/**
|
14 |
* Loads and enqueues dependencies for the plugin.
|
15 |
*
|
16 |
* @package WPA
|
17 |
* @subpackage WPA/includes
|
18 |
* @since 1.0.0
|
19 |
* @author Tom McFarlin
|
20 |
* @license http://www.gnu.org/licenses/gpl-2.0.txt
|
21 |
* @link https://tommcfarlin.com/
|
22 |
*/
|
23 |
class Dependency_Loader { |
24 |
|
25 |
/**
|
26 |
* Initializes the plugin by enqueuing the necessary dependencies.
|
27 |
*
|
28 |
* @since 1.0.0
|
29 |
*/
|
30 |
public function initialize() { |
31 |
$this->enqueue_scripts(); |
32 |
}
|
33 |
|
34 |
/**
|
35 |
* Enqueues the front-end scripts for getting the current user's information
|
36 |
* via Ajax.
|
37 |
*
|
38 |
* @access private
|
39 |
*
|
40 |
* @since 1.0.0
|
41 |
*/
|
42 |
private function enqueue_scripts() { |
43 |
|
44 |
wp_enqueue_script( |
45 |
'ajax-script', |
46 |
plugin_dir_url( dirname( __FILE__ ) ) . 'assets/js/frontend.js', |
47 |
array( 'jquery' ) |
48 |
);
|
49 |
|
50 |
wp_localize_script( |
51 |
'ajax-script', |
52 |
'sa_demo', |
53 |
array( 'ajax_url' => admin_url( 'admin-ajax.php' ) ) |
54 |
);
|
55 |
|
56 |
}
|
57 |
}
|
После этого нам нужно взять функции, отвечающие за обработку Ajax-запросов и предоставление ответов, а затем добавить их в класс. Так как они будут в контексте класса, нам нужно добавить новую функцию, которая зарегистрирует их в WordPress.
Мы создадим функцию setup_ajax_handlers
. Это выглядит так:
1 |
<?php |
2 |
|
3 |
/** |
4 |
* Registers the callback functions responsible for providing a response |
5 |
* to Ajax requests setup throughout the rest of the plugin. |
6 |
* |
7 |
* @since 1.0.0 |
8 |
*/ |
9 |
public function setup_ajax_handlers() { |
10 |
|
11 |
add_action( |
12 |
'wp_ajax_get_current_user_info', |
13 |
array( $this, 'get_current_user_info' ) |
14 |
); |
15 |
|
16 |
add_action( |
17 |
'wp_ajax_nopriv_get_current_user_info', |
18 |
array( $this, 'get_current_user_info' ) |
19 |
); |
20 |
|
21 |
} |
Затем нам нужно фактически переместить функции в этот класс. Обратите внимание, что функции, которые были изначально с префиксом _sa
, больше не помечены как таковые. Поскольку они находятся в контексте класса, мы можем отбросить префикс, а также отбросить знак подчеркивания в пользу ключевого слова private
.
1 |
<?php
|
2 |
|
3 |
public function get_current_user_info() { |
4 |
|
5 |
$user_id = get_current_user_id(); |
6 |
|
7 |
if ( $this->user_is_logged_in( $user_id ) && $this->user_exists( $user_id ) ) { |
8 |
|
9 |
wp_send_json_success( |
10 |
wp_json_encode( get_user_by( 'id', $user_id ) ) |
11 |
);
|
12 |
|
13 |
}
|
14 |
|
15 |
}
|
16 |
|
17 |
private function user_is_logged_in( $user_id ) { |
18 |
|
19 |
$is_logged_in = true; |
20 |
|
21 |
if ( 0 === $user_id ) { |
22 |
|
23 |
wp_send_json_error( |
24 |
new WP_Error( '-2', 'The visitor is not currently logged into the site.' ) |
25 |
);
|
26 |
|
27 |
$is_logged_in = false; |
28 |
|
29 |
}
|
30 |
|
31 |
return $is_logged_in; |
32 |
|
33 |
}
|
34 |
|
35 |
private function user_exists( $user_id ) { |
36 |
|
37 |
$user_exists = true; |
38 |
|
39 |
if ( false === get_user_by( 'id', $user_id ) ) { |
40 |
|
41 |
wp_send_json_error( |
42 |
new WP_Error( '-1', 'No user was found with the specified ID [' . $user_id . ']' ) |
43 |
);
|
44 |
|
45 |
$user_exists = false; |
46 |
|
47 |
}
|
48 |
|
49 |
return $user_exists; |
50 |
|
51 |
}
|
Затем мы сохраним этот файл в каталоге include
в корневом каталоге плагина. Каталог includes
включает код, который используется во всем проекте. Можно еще подробнее рассказать об этом конкретном каталоге, но это контент для более длинной статьи.
Окончательная версия этого класса должна выглядеть так:
1 |
<?php
|
2 |
/**
|
3 |
* Loads and registers dependencies.
|
4 |
*
|
5 |
* @since 1.0.0
|
6 |
*
|
7 |
* @package WPA
|
8 |
* @author Tom McFarlin
|
9 |
* @license http://www.gnu.org/licenses/gpl-2.0.txt
|
10 |
* @link https://tommcfarlin.com/
|
11 |
*/
|
12 |
|
13 |
/**
|
14 |
* Loads and enqueues dependencies for the plugin.
|
15 |
*
|
16 |
* @package WPA
|
17 |
* @subpackage WPA/includes
|
18 |
* @since 1.0.0
|
19 |
* @author Tom McFarlin
|
20 |
* @license http://www.gnu.org/licenses/gpl-2.0.txt
|
21 |
* @link https://tommcfarlin.com/
|
22 |
*/
|
23 |
class Dependency_Loader { |
24 |
|
25 |
/**
|
26 |
* Initializes the plugin by enqueuing the necessary dependencies.
|
27 |
*
|
28 |
* @since 1.0.0
|
29 |
*/
|
30 |
public function initialize() { |
31 |
$this->enqueue_scripts(); |
32 |
}
|
33 |
|
34 |
/**
|
35 |
* Enqueues the front-end scripts for getting the current user's information
|
36 |
* via Ajax.
|
37 |
*
|
38 |
* @access private
|
39 |
*
|
40 |
* @since 1.0.0
|
41 |
*/
|
42 |
private function enqueue_scripts() { |
43 |
|
44 |
wp_enqueue_script( |
45 |
'ajax-script', |
46 |
plugin_dir_url( dirname( __FILE__ ) ) . 'assets/js/frontend.js', |
47 |
array( 'jquery' ) |
48 |
);
|
49 |
|
50 |
wp_localize_script( |
51 |
'ajax-script', |
52 |
'sa_demo', |
53 |
array( 'ajax_url' => admin_url( 'admin-ajax.php' ) ) |
54 |
);
|
55 |
|
56 |
}
|
57 |
|
58 |
/**
|
59 |
* Registers the callback functions responsible for providing a response
|
60 |
* to Ajax requests setup throughout the rest of the plugin.
|
61 |
*
|
62 |
* @since 1.0.0
|
63 |
*/
|
64 |
public function setup_ajax_handlers() { |
65 |
|
66 |
add_action( |
67 |
'wp_ajax_get_current_user_info', |
68 |
array( $this, 'get_current_user_info' ) |
69 |
);
|
70 |
|
71 |
add_action( |
72 |
'wp_ajax_nopriv_get_current_user_info', |
73 |
array( $this, 'get_current_user_info' ) |
74 |
);
|
75 |
|
76 |
}
|
77 |
|
78 |
/**
|
79 |
* Retrieves information about the user who is currently logged into the site.
|
80 |
*
|
81 |
* This function is intended to be called via the client-side of the public-facing
|
82 |
* side of the site.
|
83 |
*
|
84 |
* @since 1.0.0
|
85 |
*/
|
86 |
public function get_current_user_info() { |
87 |
|
88 |
$user_id = get_current_user_id(); |
89 |
|
90 |
if ( $this->user_is_logged_in( $user_id ) && $this->user_exists( $user_id ) ) { |
91 |
|
92 |
wp_send_json_success( |
93 |
wp_json_encode( get_user_by( 'id', $user_id ) ) |
94 |
);
|
95 |
|
96 |
}
|
97 |
|
98 |
}
|
99 |
|
100 |
/**
|
101 |
* Determines if a user is logged into the site using the specified user ID. If not,
|
102 |
* then the following error code and message will be returned to the client:
|
103 |
*
|
104 |
* -2: The visitor is not currently logged into the site.
|
105 |
*
|
106 |
* @access private
|
107 |
* @since 1.0.0
|
108 |
*
|
109 |
* @param int $user_id The current user's ID.
|
110 |
*
|
111 |
* @return bool $is_logged_in Whether or not the current user is logged in.
|
112 |
*/
|
113 |
private function user_is_logged_in( $user_id ) { |
114 |
|
115 |
$is_logged_in = true; |
116 |
|
117 |
if ( 0 === $user_id ) { |
118 |
|
119 |
wp_send_json_error( |
120 |
new WP_Error( '-2', 'The visitor is not currently logged into the site.' ) |
121 |
);
|
122 |
|
123 |
$is_logged_in = false; |
124 |
|
125 |
}
|
126 |
|
127 |
return $is_logged_in; |
128 |
|
129 |
}
|
130 |
|
131 |
/**
|
132 |
* Determines if a user with the specified ID exists in the WordPress database. If not, then will
|
133 |
* the following error code and message will be returned to the client:
|
134 |
*
|
135 |
* -1: No user was found with the specified ID [ $user_id ].
|
136 |
*
|
137 |
* @access private
|
138 |
* @since 1.0.0
|
139 |
*
|
140 |
* @param int $user_id The current user's ID.
|
141 |
*
|
142 |
* @return bool $user_exists Whether or not the specified user exists.
|
143 |
*/
|
144 |
private function user_exists( $user_id ) { |
145 |
|
146 |
$user_exists = true; |
147 |
|
148 |
if ( false === get_user_by( 'id', $user_id ) ) { |
149 |
|
150 |
wp_send_json_error( |
151 |
new WP_Error( '-1', 'No user was found with the specified ID [' . $user_id . ']' ) |
152 |
);
|
153 |
|
154 |
$user_exists = false; |
155 |
|
156 |
}
|
157 |
|
158 |
return $user_exists; |
159 |
|
160 |
}
|
161 |
}
|
Основной класс
Теперь мы готовы написать основной класс для плагина. Этот конкретный класс будет находиться в корне каталога плагинов, а базовая структура класса будет выглядеть так:
1 |
<?php
|
2 |
|
3 |
/**
|
4 |
* Loads and enqueues dependencies for the plugin.
|
5 |
*
|
6 |
* @since 1.0.0
|
7 |
*
|
8 |
* @package WPA
|
9 |
*/
|
10 |
class WP_Simple_Ajax { |
11 |
|
12 |
}
|
Затем мы добавим пару свойств, которые мы установим, когда класс будет создан:
1 |
<?php
|
2 |
|
3 |
class WP_Simple_Ajax { |
4 |
|
5 |
private $version; |
6 |
|
7 |
private $loader; |
8 |
|
9 |
}
|
После этого мы создадим конструктор и функцию инициализации, которые будут использоваться для установки плагина:
1 |
<?php
|
2 |
/**
|
3 |
* The primary class for the plugin
|
4 |
*
|
5 |
* Stores the plugin version, loads and enqueues dependencies
|
6 |
* for the plugin.
|
7 |
*
|
8 |
* @since 1.0.0
|
9 |
*
|
10 |
* @package WPA
|
11 |
* @author Tom McFarlin
|
12 |
* @license http://www.gnu.org/licenses/gpl-2.0.txt
|
13 |
* @link https://tommcfarlin.com/
|
14 |
*/
|
15 |
|
16 |
/**
|
17 |
* Stores the plugin version, loads and enqueues dependencies
|
18 |
* for the plugin.
|
19 |
*
|
20 |
* @package WPA
|
21 |
* @author Tom McFarlin
|
22 |
* @license http://www.gnu.org/licenses/gpl-2.0.txt
|
23 |
* @link https://tommcfarlin.com/
|
24 |
*/
|
25 |
class WP_Simple_Ajax { |
26 |
|
27 |
/**
|
28 |
* Represents the current version of this plugin.
|
29 |
*
|
30 |
* @access private
|
31 |
* @since 1.0.0
|
32 |
* @var string
|
33 |
*/
|
34 |
private $version; |
35 |
|
36 |
/**
|
37 |
* A reference to the Dependency Loader.
|
38 |
*
|
39 |
* @access private
|
40 |
* @since 1.0.0
|
41 |
* @var Dependency_Loader
|
42 |
*/
|
43 |
private $loader; |
44 |
|
45 |
/**
|
46 |
* Initializes the properties of the class.
|
47 |
*
|
48 |
* @access private
|
49 |
* @since 1.0.0
|
50 |
*/
|
51 |
public function __construct() { |
52 |
|
53 |
$this->version = '1.0.0'; |
54 |
$this->loader = new Dependency_Loader(); |
55 |
|
56 |
}
|
57 |
|
58 |
/**
|
59 |
* Initializes this plugin and the dependency loader to include
|
60 |
* the JavaScript necessary for the plugin to function.
|
61 |
*
|
62 |
* @access private
|
63 |
* @since 1.0.0
|
64 |
*/
|
65 |
public function initialize() { |
66 |
|
67 |
$this->loader->initialize(); |
68 |
$this->loader->setup_ajax_handlers(); |
69 |
|
70 |
}
|
71 |
}
|
В приведенном выше коде конструктор задает свойства и создает зависимости, необходимые для приведения плагина в движение.
Когда вызывается initialize
, плагин запускается и вызывает метод initialize для класса зависимостей, который мы создали ранее в этом уроке.
Bootstrap
Последнее, что нам нужно сделать, - это взять основной файл, который у нас есть, использовать функцию PHP include
и убедиться, что он знает о необходимых PHP-файлах, которые у нас есть.
1 |
<?php
|
2 |
|
3 |
/**
|
4 |
* Loads and registers dependencies.
|
5 |
*/
|
6 |
include_once( 'includes/class-dependency-loader.php' ); |
7 |
|
8 |
/**
|
9 |
* The primary class for the plugin
|
10 |
*/
|
11 |
include_once( 'class-wp-simple-ajax.php' ); |
После этого нам нужно определить метод, который инициализирует основной файл плагина и приводит все в действие.
1 |
<?php
|
2 |
|
3 |
/**
|
4 |
* Instantiates the main class and initializes the plugin.
|
5 |
*/
|
6 |
function wpa_start_plugin() { |
7 |
|
8 |
$plugin = new WP_Simple_Ajax(); |
9 |
$plugin->initialize(); |
10 |
|
11 |
}
|
Окончательная версия загрузочного файла должна выглядеть так:
1 |
<?php
|
2 |
/**
|
3 |
* This plugin demonstrates how to use the WordPress Ajax APIs.
|
4 |
*
|
5 |
* @package WPA
|
6 |
*
|
7 |
* @wordpress-plugin
|
8 |
* Plugin Name: Simple Ajax Demo
|
9 |
* Description: A simple demonstration of the WordPress Ajax APIs.
|
10 |
* Version: 1.0.0
|
11 |
* Author: Tom McFarlin
|
12 |
* Author URI: https://tommcfarlin.com/
|
13 |
* License: GPL-2.0+
|
14 |
* License URI: http://www.gnu.org/licenses/gpl-2.0.txt
|
15 |
*/
|
16 |
|
17 |
// If this file is called directly, abort.
|
18 |
if ( ! defined( 'WPINC' ) ) { |
19 |
die; |
20 |
}
|
21 |
|
22 |
/**
|
23 |
* Loads and registers dependencies.
|
24 |
*/
|
25 |
include_once( 'includes/class-dependency-loader.php' ); |
26 |
|
27 |
/**
|
28 |
* The primary class for the plugin
|
29 |
*/
|
30 |
include_once( 'class-wp-simple-ajax.php' ); |
31 |
|
32 |
/**
|
33 |
* Instantiates the main class and initializes the plugin.
|
34 |
*/
|
35 |
function wpa_start_plugin() { |
36 |
|
37 |
$plugin = new WP_Simple_Ajax(); |
38 |
$plugin->initialize(); |
39 |
|
40 |
}
|
41 |
wpa_start_plugin(); |
Во-первых, файл проверяет, можно ли получить доступ к нему напрямую, проверив, была ли определена константа WordPress. Если нет, то выполнение останавливается.
После этого он включает в себя различные классы, которые мы создали в этом уроке. Наконец, он определяет функцию, которая вызывается, когда WordPress загружает плагин, который запускает плагин и запускает все в движение.
Заключение
И вот мы подошли к концу этой серии из двух частей. Надеемся, вы узнали не только о некоторых лучших методах включения Ajax в ваши проекты WordPress, но также немного о документировании как процедурного, так и объектно-ориентированного кода, а также о различиях в них.
В будущем посте я могу вернуться к некоторым объектно-ориентированным концепциям, которые были введены здесь, и более подробно их описывать. А пока взглянем на плагин, используя ссылку GitHub на боковой панели этой страницы.
Помните, что вы можете отслеживать все мои курсы и учебные материалы на моей странице в профиле, и вы можете следить за мной в моем блоге и/или Twitter в @tommcfarlin, где я рассказываю о разработке программного обеспечения в контексте WordPress.
Как обычно, пожалуйста, не стесняйтесь оставлять любые вопросы или комментарии в ленте ниже, и я постараюсь ответить на каждый из них.