Статьи

Улучшенные технологии Ajax для WordPress: объектно-ориентированное программирование

В предыдущем посте этой серии мы вновь рассмотрели тему работы с Ajax в WordPress. В конечном счете, цель состоит в том, чтобы улучшить предыдущую серию, которая была запущена на сайте несколько лет назад.

Повторюсь, дело не в том, что методы, преподаваемые в оригинальной серии, были неправильными, а в том, что программное обеспечение меняется со временем, поэтому всегда полезно пересмотреть концепции, которые рассматривались много лет назад, и попытаться обновить их до чего-то более современного и более гибкого. для наших усилий по развитию.

Напомним, из предыдущего поста мы рассмотрели следующий комментарий из оригинальной серии:

Мы собираемся дать очень краткий обзор того, что такое Ajax, как он работает, как настроить его на лицевой стороне, и понять, что предоставляет WordPress. Мы также на самом деле создадим небольшой проект, который применяет теорию на практике. Мы пройдемся по исходному коду и также убедимся, что он доступен и на GitHub.

И в этом посте мы рассмотрели некоторые продвинутые способы включения WordPress Ajax API в наши проекты с использованием процедурного программирования. В этой статье мы собираемся взять код, который мы написали в первой части этой серии, и реорганизовать его так, чтобы он использовал объектно-ориентированный подход.

В конечном счете, цель состоит не в том, чтобы обосновать, почему одну парадигму следует использовать над другой; вместо этого он показывает, как мы можем достичь той же функциональности независимо от подхода, который вы выбрали при создании своих плагинов.

Прежде чем мы приступим к рефакторингу кода, мы должны рассмотреть, как мы будем размещать различные файлы. В конце концов, часть процесса начала нового проекта или даже перехода к старому — это планирование того, как будет выполняться работа.

Для этого конкретного плагина нам понадобится следующее:

  • загрузочный файл, который отвечает за инициализацию основного класса и запуск плагина
  • класс, который отвечает за загрузку зависимостей, таких как JavaScript
  • класс, который служит основным классом плагина

Как вы можете видеть, нам не нужно делать слишком много для плагина. Мы также будем реорганизовывать некоторые файлы, чтобы они имели согласованную структуру каталогов, и мы будем должным образом документировать весь код, чтобы он соответствовал стандартам кодирования WordPress .

С этим сказал, давайте начнем.

Прежде чем мы начнем писать код, давайте продолжим и сделаем следующее:

  1. Создайте каталог assets .
  2. Создайте каталог js который будет расположен в каталоге assets .
  3. Переместите frontend.js в каталог js .
Каталог активов

Причина этого заключается в том, что мы переходим к объектно-ориентированному стилю программирования. Частично это включает в себя организацию наших файлов таким образом, чтобы они следовали соглашениям, часто рассматриваемым как пакеты.

В нашем случае каталог assets содержит все необходимое для запуска программы. Для некоторых плагинов это может быть JavaScript, CSS, изображения, шрифты и так далее. В этом случае у нас есть один файл JavaScript.

Далее нам нужно ввести класс, который будет отвечать за загрузку зависимостей для нашего проекта. Для этого конкретного плагина единственной зависимостью, которую мы имеем, является файл JavaScript, который мы только что поместили в каталог assets .

Частью объектно-ориентированного программирования является обеспечение того, чтобы у каждого класса была определенная цель. В этом случае класс, который мы собираемся представить, будет отвечать за загрузку JavaScript с помощью API WordPress.

Давайте начнем с создания базовой структуры класса:

01
02
03
04
05
06
07
08
09
10
11
12
<?php
     
/**
 * Loads and enqueues dependencies for the plugin.
 *
 * @since 1.0.0
 *
 * @package WPA/includes
 */
class Dependency_Loader {
     
}

Далее мы добавим метод, который будет отвечать за постановку в очередь JavaScript согласно API WordPress.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
<?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__ ) ) .
            array( ‘jquery’ )
        );
 
        wp_localize_script(
            ‘ajax-script’,
            ‘sa_demo’,
            array( ‘ajax_url’ => admin_url( ‘admin-ajax.php’ ) )
        );
 
    }
}

После этого нам нужно взять функции, отвечающие за обработку запросов Ajax и предоставление ответов, а затем добавить их в класс. Так как они будут в контексте класса, нам нужно добавить новую функцию, которая зарегистрирует их в WordPress.

Мы создадим функцию setup_ajax_handlers . Это выглядит так:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
<?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 .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<?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;
 
}

Затем мы сохраним этот файл в каталоге include в корне каталога плагина. В каталоге include часто находится код, используемый в проекте. Об этом конкретном каталоге можно сказать больше, но это содержание для более длинного поста.

Окончательная версия этого класса должна выглядеть так:

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
<?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__ ) ) .
            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.
     * 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.
     * 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;
 
    }
}

Теперь мы готовы написать основной класс для плагина. Этот конкретный класс будет находиться в корне каталога плагинов, и базовая структура класса будет выглядеть следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
<?php
 
/**
 * Loads and enqueues dependencies for the plugin.
 *
 * @since 1.0.0
 *
 * @package Acme
 */
class Acme_Simple_Ajax {
     
}

Далее мы добавим пару свойств, которые мы установим при создании экземпляра класса:

1
2
3
4
5
6
7
8
9
<?php
 
class Acme_Simple_Ajax {
 
    private $version;
 
    private $loader;
 
}

После этого мы создадим конструктор и функцию инициализации, которые будут использоваться для запуска плагина:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
<?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 для класса зависимостей, который мы создали ранее в этом уроке.

Последнее, что нам нужно сделать, — это взять основной файл, который у нас есть, использовать функцию include PHP и убедиться, что он знает о необходимых файлах PHP, которые у нас есть.

01
02
03
04
05
06
07
08
09
10
11
<?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’ );

После этого нам нужно определить метод, который будет инициализировать основной файл плагина и привести все в движение.

01
02
03
04
05
06
07
08
09
10
11
<?php
 
/**
 * Instantiates the main class and initializes the plugin.
 */
function acme_start_plugin() {
 
    $plugin = new Acme_Simple_Ajax();
    $plugin->initialize();
 
}

Окончательная версия файла начальной загрузки должна выглядеть следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?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 на боковой панели этой страницы.

Помните, что вы можете просмотреть все мои курсы и учебные пособия на странице моего профиля , и вы можете следить за мной в моем блоге и / или Twitter по адресу @tommcfarlin, где я говорю о разработке программного обеспечения в контексте WordPress.

Как обычно, пожалуйста, не стесняйтесь оставлять любые вопросы или комментарии в ленте ниже, и я постараюсь ответить на каждый из них.