() translation by (you can also view the original English article)
Несколько лет назад я написал серию сообщений о том, как использовать Ajax в WordPress Frontend. Цель серии проста:
Мы собираемся дать очень краткий обзор того, что такое Ajax, как он работает, как настроить его на передней панели и понять, какие ловушки поддерживает WordPress. Мы также создадим небольшой проект, который воплотит эту теорию в жизнь. Мы пройдем через исходный код, и мы также убедимся, что он доступен и на GitHub.
Вообще говоря, серия держится хорошо, но, как и во всем программном обеспечении при постоянной разработке, методы, API и подходы меняются. Более того, по мере того, как проходят годы, и мы продолжаем совершенствовать свои навыки, мы совершенствуемся при разработке, и мы лучше используем новые API.
Из-за всего вышеизложенного я хочу вернуться к концепции Ajax в WordPress, чтобы вы увидели некоторые из новых API и как использовать их в своей повседневной работе или как реорганизовать некоторый код, который вы можете использовать С прямо сейчас.
Слово предостережения, прежде чем зайти слишком далеко в этот учебник: я предполагаю, что вы уже прочитали серию, связанную во введении этой статьи, и что у вас есть некоторый опыт создания плагинов WordPress.
Определение плагина
Как и в любом плагине WordPress, важно удостовериться, что вы определяете заголовок, чтобы WordPress мог прочитать файл, чтобы добавить новые функции в основное приложение.
Я называю этот вариант плагина Simple Ajax Demo, и он находится в wp-content/plugin/wp-simple-ajax
. Первый созданный файл находится в корневом каталоге wp-simple-ajax
и называется wp-simple-ajax.php
.
Это выглядит так:
1 |
<?php
|
2 |
|
3 |
/**
|
4 |
* Plugin Name: Simple Ajax Demo
|
5 |
* Description: A simple demonstration of the WordPress Ajax APIs.
|
6 |
* Version: 1.0.0
|
7 |
* Author: Tom McFarlin
|
8 |
* Author URI: https://tommcfarlin.com/
|
9 |
* License: GPL-2.0+
|
10 |
* License URI: https://www.gnu.org/licenses/gpl-2.0.txt
|
11 |
*/
|
Код должен быть понятным, особенно если вы привыкли работать с плагинами WordPress; Однако, самое важное, понять, что вся информация выше - это то, что будет управлять тем, что видит пользователь на панели инструментов WordPress.
То есть, пользователи будут видеть имя, описание и версию плагина, а также имя автора (которое будет связано с указанным URL-адресом), когда им будет предложено активировать плагин.
Добавление файла Ajax для WordPress
На данный момент плагин появится в панели инструментов WordPress Plugin, но на самом деле он ничего еще не делает, потому что мы не написали никакого кода. Чтобы код заработал, мы использовать в этом плагине процедурный подход к программированию, а не к объектно-ориентированный, который я использовал в большинстве моих обучающих программ.
Как мы первоначально добавили поддержку Ajax
Причина, по которой в настоящее время избегают объектно-ориентированного программирования, двоякая:
- Это связано с тем, что плагин будет очень простым. Мне больше интересно сосредоточиться на указанных API, предоставляемых WordPress, чтобы вы могли сконцентрировать внимание на самых важных вещах, на которых нужно сосредоточиться в этой работе.
- Вторая часть этой серии будет посвящена рефакторингу этого кода в объектно-ориентированную систему, чтобы вы могли увидеть, как все это может выглядеть в контексте более крупной системы, использующей классы.
В конечном счете, эта серия будет охватывать оба типа программирования, поддерживаемые PHP и WordPress.
Скорее всего, если вы уже работали с Ajax в прошлом, вы делали что-то подобное, чтобы предоставить вашему плагину поддержку для выполнения асинхронных вызовов:
1 |
<?php
|
2 |
add_action( 'wp_head','acme_add_ajax_support' ); |
3 |
function acme_add_ajax_support() { |
4 |
?>
|
5 |
<script type="text/javascript"> |
6 |
var ajaxurl = '<?php echo admin_url( 'admin-ajax.php' ); ?>'; |
7 |
</script>
|
8 |
<?php
|
9 |
}
|
Этот специфический метод не является по своей сути неправильным, но он пренебрегает некоторыми новыми API, которые я рассмотрю вкратце. Он также смешивает PHP, HTML и JavaScript в одной функции.
Это не очень здорово, поскольку он выполняет свою работу, но есть более чистый способ сделать это.
Как мы добавляем поддержку Ajax
Во-первых, чтобы убедиться, что плагин не может быть напрямую доступен кому-либо, добавьте следующее условное под заголовком плагина:
1 |
<?php
|
2 |
|
3 |
// If this file is called directly, abort.
|
4 |
if ( ! defined( 'WPINC' ) ) { |
5 |
die; |
6 |
}
|
Обратите внимание, что открывающий тег PHP не понадобится, поскольку этот код появится позже в уже существующем файле PHP (это необходимо для подсветки синтаксиса прямо сейчас).
Далее давайте настроим функцию для включения поддержки WordPress для Ajax с помощью некоторых из существующих API, которые не предполагают смешение языков.
Вот что нам нужно сделать:
- Мы собираемся создать функцию, отвечающую за добавление поддержки Ajax.
- Мы подключим эту функцию в действие
wp_enqueue_script
. - Мы воспользуемся вызовом API
wp_localize_script
, чтобы включить поддержку WordPress для Ajax (которая поступает изadmin-ajax.php
).
Выглядит достаточно просто, не так ли? Обратите внимание, если у вас есть какие-либо вопросы, вы всегда можете задать их в комментариях. Прочитайте следующий код, чтобы узнать, можете ли вы следовать вместе со мной дальше:
1 |
<?php
|
2 |
|
3 |
add_action( 'wp_enqueue_scripts', 'sa_add_ajax_support' ); |
4 |
/**
|
5 |
* Adds support for WordPress to handle asynchronous requests on both the front-end
|
6 |
* and the back-end of the website.
|
7 |
*
|
8 |
* @since 1.0.0
|
9 |
*/
|
10 |
function sa_add_ajax_support() { |
11 |
|
12 |
wp_localize_script( |
13 |
'ajax-script', |
14 |
'sa_demo', |
15 |
array( |
16 |
'ajaxurl' => admin_url( 'admin-ajax.php' ) |
17 |
)
|
18 |
);
|
19 |
|
20 |
}
|
Опять же, обратите внимание, что открывающий тег PHP не потребуется в окончательной версии плагина, так как здесь он используется только для подсветки синтаксиса.
С учетом сказанного, взгляните на wp_localize_script
. Прежде чем рассматривать каждый параметр, давайте рассмотрим назначение этой функции. Из Codex короткая версия выглядит следующим образом:
Локализует зарегистрированный сценарий с данными для переменной JavaScript.
Однако более важное значение имеет более длинное описание:
Это позволяет вам предлагать правильно локализованные переводы любых строк, используемых в вашем скрипте. Это необходимо, потому что WordPress в настоящее время предлагает API локализации только в PHP, а не непосредственно в JavaScript.
Хотя локализация - это основное применение, ее можно использовать для того, чтобы любые имеющиеся в вашем скрипте данные были доступны только с сервера WordPress.
Теперь просмотрите параметры, которые он принимает:
- Первый параметр называется
handle
и используется для уникальной идентификации скрипта, который добавляется на страницу. - Второй параметр -
name
важный, поскольку именно так вы будете идентифицировать сценарий в своем коде. Вы увидите это более подробно позже в этом уроке. - Третий параметр - это параметр данных. Он ссылается на массив, который будет отправлен в браузер как объект JavaScript. Поскольку мы передаем URL-адрес пути к файлу, будет предоставлена поддержка Ajax.
Обратите внимание, что первым параметром является ajax-script
. Помните об этом, когда мы обращаем внимание на написание и добавление в очередь нашего собственного JavaScript, поскольку нам нужно использовать этот дескриптор еще раз.
Также не забудьте указать имя, которое вы выбрали для своего вызова API, поскольку мы будем использовать его при работе с клиентским кодом далее в этом уроке.
Важная информация о поддержке Ajax
Обратите внимание, что мы используем только хук wp_enqueue_script
, и мы не используем admin_enqueue_script
. Это связано с тем, что ajaxurl
уже определен в панели мониторинга.
Это означает, что если вы хотите сделать Ajax-запросы в области администрирования WordPress, вам не нужно ничего ставить в очередь. Все, что мы делаем в контексте этого учебника, направлено для внешнего интерфейса веб-сайта.
Настройка вашего кода на стороне сервера
Теперь пришло время написать функцию, которую ваш JavaScript вызовет через Ajax. Это может быть все, что вы хотите, но для целей этого плагина мы собираемся настроить функцию, которая будет возвращать информацию о пользователе, который зарегистрирован на сайте.
Плагин выполнит следующие действия:
- Выполните запрос к серверу, запрашивая информацию о текущем пользователе.
- Если пользователь зарегистрируется на сайте, он вернет ответ JSON от информации пользователя.
- Если пользователь не вошел в систему, он вернет код ошибки.
Мы будем использовать объект console
доступный в большинстве современных браузеров, поэтому убедитесь, что используете Chrome, Safari или Firefox при работе с исходным кодом JavaScript, который вы будете писать.
Отправляем запрос
Теперь, когда мы наметили, как именно код будет работать, когда пользователь отправит запрос Ajax на сервер, давайте начнем писать функцию для этого. Мы назовем его sa_get_user_information
.
1 |
<?php
|
2 |
|
3 |
add_action( 'wp_ajax_get_current_user_info', 'sa_get_current_user_info' ); |
4 |
add_action( 'wp_ajax_nopriv_get_current_user_info', 'sa_get_current_user_info' ); |
5 |
/**
|
6 |
* Retrieves information about the user who is currently logged into the site.
|
7 |
*
|
8 |
* This function is intended to be called via the client-side of the public-facing
|
9 |
* side of the site.
|
10 |
*
|
11 |
* @since 1.0.0
|
12 |
*/
|
13 |
function sa_get_current_user_info() { |
14 |
|
15 |
}
|
Реализация функции будет позже в этом уроке, но основной вывод из вышеприведенного кода состоит в том, что мы подключились как к wp_ajax_get_current_user_info
, так и к wp_ajax_nopriv_get_current_user_info
.
Эти два хука хорошо документированы в Codex, но первый хук позволит тем, кто вошел на сайт, получить доступ к этой функции. Второй хук позволит тем, кто не вошел на этот сайт, получить доступ к этой функции.
Также обратите внимание, что все после wp_ajax_
и wp_ajax_nopriv_
зависит от вас, как разработчика, это должны определить вы сами. Это будет имя функции, которую вы вызываете с клиентской стороны, как вы увидите далее в этом уроке.
Обработка ошибочных запросов
Перед реализацией функции был вызван исходный файл JavaScript (который еще не был написан), и нам нужно убедиться, что мы сможем справиться с любыми ошибками, которые могут произойти.
В нашем случае потенциальными ошибками могут быть:
- Никто не подключен.
- ИД пользователя не существует в системе.
Очень маловероятно, что второй случай будет правдой, но это поможет нам узнать больше о еще нескольких API-интерфейсах WordPress и о том, как мы можем использовать их для обработки ошибочных запросов.
Первое, что нужно понять, это WP_Error
. Как и многие API, это доступно в Codex:
Экземпляры кодов ошибок и сообщений об ошибках WP_Error, представляющие одну или несколько ошибок, и возможность того, является ли переменная экземпляром WP_Error, могут быть определены с помощью функции is_wp_error().
Конструктор принимает до трех параметров (хотя мы будем использовать только первые два):
- Первый аргумент - это код ошибки. Это то, что мы можем использовать на стороне клиента для разбора и определения того, что пошло не так. Это также позволяет нам записывать информацию в файл журнала и так далее.
- Второй аргумент - это сообщение, которое может сопровождать код ошибки. Это полезно, если мы хотим отобразить сообщение пользователю.
- Последний аргумент - массив информации, обычно коды ошибок и сообщения. Несмотря на это, мы не будем использовать его в нашем коде.
Затем мы отправим результаты ошибок обратно клиенту с помощью функции wp_send_json_error
. Это очень просто сделать:
Отправьте ответ JSON обратно на запрос Ajax, указывая на сбой. Объект ответа всегда будет иметь ключ успеха со значением false. Если что-либо передается функции в параметре $data, то оно будет закодирована как значение для ключа данных.
Объединив оба WP_Error
и wp_send_json_error
, мы можем создать функции, которые помогут нам предоставить коды ошибок JavaScript, вызывающим серверную часть.
Например, предположим, что у нас есть функция, предоставляющая сообщение об ошибке, если пользователь не вошел на сайт. Это может быть реализовано с помощью следующей функции:
1 |
<?php
|
2 |
|
3 |
/**
|
4 |
* Determines if a user is logged into the site using the specified user ID. If not,
|
5 |
* then the following error code and message will be returned to the client:
|
6 |
*
|
7 |
* -2: The visitor is not currently logged into the site.
|
8 |
*
|
9 |
* @access private
|
10 |
* @since 1.0.0
|
11 |
*
|
12 |
* @param int $user_id The current user's ID.
|
13 |
*/
|
14 |
function _sa_user_is_logged_in( $user_id ) { |
15 |
|
16 |
if ( 0 === $user_id ) { |
17 |
|
18 |
wp_send_json_error( |
19 |
new WP_Error( '-2', 'The visitor is not currently logged into the site.' ) |
20 |
);
|
21 |
|
22 |
}
|
23 |
|
24 |
}
|
Обратите внимание: функция отмечена как private, даже если она находится в глобальном пространстве имен. Он имеет префикс с подчеркиванием, чтобы обозначить эту функцию конфиденциальной.
Мы вернемся к этому в следующей статье.
Во-вторых, мы должны обработать сценарий, если пользователь не существует. Для этого мы можем создать функцию, которая выполняет следующее:
1 |
<?php |
2 |
|
3 |
/**
|
4 |
* Determines if a user is logged into the site using the specified user ID. If not,
|
5 |
* then the following error code and message will be returned to the client:
|
6 |
*
|
7 |
* -2: The visitor is not currently logged into the site.
|
8 |
*
|
9 |
* @access private
|
10 |
* @since 1.0.0
|
11 |
*
|
12 |
* @param int $user_id The current user's ID.
|
13 |
*/
|
14 |
function _sa_user_is_logged_in( $user_id ) { |
15 |
|
16 |
if ( 0 === $user_id ) { |
17 |
|
18 |
wp_send_json_error( |
19 |
new WP_Error( '-2', 'The visitor is not currently logged into the site.' ) |
20 |
);
|
21 |
|
22 |
}
|
23 |
|
24 |
}
|
Теперь у нас есть две функции, каждая из которых будет отправлять информацию клиенту, если что-то не пошло не так, но что мы будем делать, если обе эти функции пройдут?
Обработка успешных запросов
Если приведенные выше функции не приводят к ошибкам, нам нужно иметь способ отправить запрос обратно клиенту с успешным сообщением и информацией, которую он запрашивает.
А именно, нам нужно отправить информацию обратно клиенту, которая содержит данные текущего пользователя в формате JSON.
Для этого мы можем воспользоваться сообщением wp_send_json_success
. Оно делает то, что, по вашему мнению и должно делать:
Отправляет ответ JSON обратно на запрос Ajax, указывая на успех. Объект ответа всегда будет иметь ключ успеха со значением true. Если что-либо передано функции, оно будет закодировано как значение для ключа данных.
Давайте объединим работу, которую мы сделали до сих пор, чтобы написать функцию, которую JavaScript в конечном итоге вызовет, и которая использует две меньшие функции, которые мы разместили выше. Фактически, это будет реализация функции, которую мы пропустили ранее в этом уроке:
1 |
<?php
|
2 |
|
3 |
add_action( 'wp_ajax_get_current_user_info', 'sa_get_current_user_info' ); |
4 |
add_action( 'wp_ajax_nopriv_get_current_user_info', 'sa_get_current_user_info' ); |
5 |
/**
|
6 |
* Retrieves information about the user who is currently logged into the site.
|
7 |
*
|
8 |
* This function is intended to be called via the client-side of the public-facing
|
9 |
* side of the site.
|
10 |
*
|
11 |
* @since 1.0.0
|
12 |
*/
|
13 |
function sa_get_current_user_info() { |
14 |
|
15 |
// Grab the current user's ID
|
16 |
$user_id = get_current_user_id(); |
17 |
|
18 |
// If the user is logged in and the user exists, return success with the user JSON
|
19 |
if ( _sa_user_is_logged_in( $user_id ) && _sa_user_exists( $user_id ) ) { |
20 |
|
21 |
wp_send_json_success( |
22 |
json_encode( get_user_by( 'id', $user_id ) ) |
23 |
);
|
24 |
|
25 |
}
|
26 |
|
27 |
}
|
Если пользователь зарегистрирован и пользователь существует, то мы отправим клиенту сообщение об успешном завершении, содержащее JSON представление пользователя. На этом этапе пришло время написать немного JavaScript.
Запрос на стороне клиента
Сначала добавьте файл с именем frontend.js
в корневой каталог вашего плагина. Первоначально он должен содержать следующий код:
1 |
;(function( $ ) { |
2 |
'use strict'; |
3 |
|
4 |
$(function() { |
5 |
|
6 |
});
|
7 |
|
8 |
})( jQuery ); |
Реализация функции будет покрыта на мгновение, но нам нужно убедиться, что мы добавим этот файл JavaScript в плагин. Вернитесь к функции sa_add_ajax_support
и добавьте следующий выше вызов wp_localize_script
:
1 |
<?php
|
2 |
|
3 |
wp_enqueue_script( |
4 |
'ajax-script', |
5 |
plugin_dir_url( __FILE__ ) . 'frontend.js', |
6 |
array( 'jquery' ) |
7 |
);
|
Помните, этот скрипт должен иметь тот же дескриптор, что и тот, который определен в wp_localize_script. Теперь мы можем вернуться к нашему файлу JavaScript и сделать звонок на серверный код, над которым мы работали всю эту статью.
В файле frontend.js
добавьте следующий код:
1 |
/**
|
2 |
* This file is responsible for setting up the Ajax request each time
|
3 |
* a WordPress page is loaded. The page could be the main index page,
|
4 |
* a single page, or any other type of information that WordPress renders.
|
5 |
*
|
6 |
* Once the DOM is ready, it will make an Ajax call to the server where
|
7 |
* the `get_current_user_info` function is defined and will then handle the
|
8 |
* response based on the information returned from the request.
|
9 |
*
|
10 |
* @since 1.0.0
|
11 |
*/
|
12 |
;(function( $ ) { |
13 |
'use strict'; |
14 |
|
15 |
$(function() { |
16 |
|
17 |
/* Make an Ajax call via a GET request to the URL specified in the
|
18 |
* wp_enqueue_script call. For the data parameter, pass an object with
|
19 |
* the action name of the function we defined to return the user info.
|
20 |
*/
|
21 |
$.ajax({ |
22 |
|
23 |
url: sa_demo.ajax_url, |
24 |
method: 'GET', |
25 |
data: { action: 'get_current_user_info' } |
26 |
|
27 |
}).done(function( response ) { |
28 |
|
29 |
/* Once the request is done, determine if it was successful or not.
|
30 |
* If so, parse the JSON and then render it to the console. Otherwise,
|
31 |
* display the content of the failed request to the console.
|
32 |
*/
|
33 |
if ( true === response.success ) { |
34 |
|
35 |
console.log( JSON.parse( response.data ) ); |
36 |
|
37 |
} else { |
38 |
|
39 |
console.log( response.data ); |
40 |
|
41 |
}
|
42 |
|
43 |
});
|
44 |
|
45 |
});
|
46 |
|
47 |
})( jQuery ); |
Учитывая количество комментариев в коде и предполагая, что вы знакомы с написанием плагинов WordPress и имеете некоторый опыт работы с Ajax, все это для вас должно было быть относительно легко.
Короче говоря, код выше делает вызов серверной стороны, когда страница загружается, а затем записывает информацию на консоль браузера о текущем пользователе.
Если пользователь вошел в систему, информация записывается в консоль в виде объекта JavaScript, поскольку он обрабатывается из JSON.
Если, с другой стороны, пользователь не вошел в систему, тогда будет выписан другой объект, отображающий код ошибки вместе с сообщением, которые вы сможете увидеть в консоли.
Заключение
К настоящему времени у вас должно быть четкое представление о API-интерфейсах, которые WordPress может использовать для работы с запросами Ajax для пользователей, которые вошли на сайт, а также для тех, кто этого не сделал.
В конечном счете, наша цель не заключалась в том, чтобы написать самый чистый, самый поддерживаемый код, а наоборот в том, чтобы у нас была возможность продолжить работу с этим кодом по мере продвижения в будущее. Кроме того, мы должны написать такой код, чтобы другие пользователи, которые могут воспользоваться нашей кодовой базы, получили четкое представление о том, что мы пытаемся сделать.
В этом уроке я использовал процедурный подход к программированию для всего кода, который был совместно использован, продемонстрирован и предоставлен через GitHub. Как уже упоминалось ранее, в этом нет ничего изначально неправильного, но я действительно думаю, что стоит посмотреть, как это выглядит с объектно-ориентированной точки зрения.
В следующем уроке мы рассмотрим рефакторинг этого кода в объектно-ориентированную парадигму, которая также использует стандарты кодирования WordPress для дальнейшего документирования нашей работы, и которая использует четкую организацию файлов, чтобы сделать наш код максимально понятным.
Помните, что вы можете отслеживать все мои курсы и учебные материалы на моей странице в профиле, и вы можете следить за мной в моем блоге и/или Twitter в @tommcfarlin, где я рассказываю о разработке программного обеспечения в контексте WordPress.
Тем временем, пожалуйста, не стесняйтесь оставлять любые вопросы или комментарии в фиде ниже, и я постараюсь ответить на каждый из них.