Использование «Ajax» является одним из самых распространенных методов создания и работы с пользовательскими интерфейсами.
Применение этой технологии позволяет выполнять незаметную фоновую обработку данных (без перезагрузки страницы), что значительно улучшает процесс взаимодействия пользователей с сайтом.
В качестве примера, работу Ajax в WordPress можно наблюдать в панели администратора если открыть консоль браузера и перейти во вкладку «Network», но, как и везде, в WordPress есть свои особенности работы с асинхронным JavaScript и в этой статье мы на их рассмотрим.
Содержание
Что будем делать?
Осваивать работу Ajax в WordPress мы будем на реальном примере, а именно будем создавать форму регистрации и авторизации пользователей, для вашего WordPress сайта.
Только реальная практика, только хардкор ?
WordPress лаборатория
Формы, которые вы видите ниже, будут результатом нашей совместной работы. Они полностью рабочие, пробуйте.
Внимание
Так как это обучающие пособие, то все пользователи, которые зарегистрировались через эту форму, периодически удаляются!
Авторизация
Регистрация
Внимание
Предполагается, что читатель уже обладает базовыми навыками работы с HTML, CSS, PHP и jQuery, так как мы не будем посимвольно разжёвывать каждый кусок кода.
Начать погружение в работу Ajax на WordPress сайтах следует с изучения теории, этим и займёмся.
Теория использования Ajax в WordPress
Начиная с бородатой версии ядра 2.8, WordPress позволяем создавать собственные события, используя встроенный Ajax, но стоит понимать, что есть ряд правил, которым нужно следовать:
- Все запросы должны передаваться с использованием файла admin-ajax.php, не нужно писать собственные обработчики.
- Права на использования событий обработки асинхронных запросов должны быть правильно разграничены.
- Использование nonce (Hash, с определенным жизненным циклом), значительно уменьшает вероятность неправомерного использования события.
- Событие должно заканчиваться функцией wp_die(), а не die() или exit(). Сторонние разработчики часто используют фильтрацию функции wp_die(), не лишайте их этой возможности. К тому же эта функция полезна при отладке кода.
Как видно, свод правил достаточно коротки и никаких критичных ограничений не несет.
Давайте уже переходить к практике.
Практика работы с Ajax в WordPress
Первое, что нам предстоит сделать – это создать HTML разметку форм для регистрации/авторизации и стилизовать их. Процесс этот описывать не будем, а сам код можно взять здесь.
Стоит учесть, что таблица стилей вашей темы может частично перекрыть стили форм, с которыми мы работаем, но в целом должно получиться примерно так:
Для начала, советуем не менять HTML разметку, которая используется в этом уроке, а просто скопировать и вставить в тело страницы, используя элемент HTML в редакторе блоков.
Скрипты в этом уроке будет опираться именно на эту разметку.
Событие инициализации JS скрипта
Вставляем этот код в functions.php вашей темы (желательно дочерней):
// Добавляем событие в процесс инициализации JS скриптов add_action( 'wp_enqueue_scripts', 'wplb_ajax_enqueue' ); //Описываем событие function wplb_ajax_enqueue() { // Подключаем файл js скрипта. wp_enqueue_script( 'wplb-ajax', // Имя get_stylesheet_directory_uri() . '/scripts/wplb-ajax.js', // Путь до JS файла. array('jquery') // В массив jquery. ); // Используем функцию wp_localize_script для передачи переменных в JS скрипт. wp_localize_script( 'wplb-ajax', // Куда будем передавать 'wplb_ajax_obj', // Название массива, который будет содержать передаваемые данные array( 'ajaxurl' => admin_url( 'admin-ajax.php' ), // Элемент массива, содержащий путь к admin-ajax.php 'nonce' => wp_create_nonce('wplb-nonce') // Создаем nonce ) ); }
Давайте подробнее рассмотрим это кусок кода:
Первое, что мы делаем, хукаем событие инициализации скриптов для регистрации собственного *.js.
Обратите внимание, что мы используем функцию get_stylesheet_directory_uri(), для того, чтобы указать путь к новому JS файлу так как работаем в дочерней теме. Если вы работаете в родительской теме, то используйте функцию get_template_directory_uri().
Благодаря функции wp_localize_script(), а в файле /scripts/wplb-ajax.js, будет доступен объект с данными которые мы отправляем из PHP. Имейте ввиду, что таким методом можно передавать любые, как статичные данные из БД, так и результаты отработки циклов ☝️
Изначальное тело подключённого скрипта
Для начала, содержимое файла wplb-ajax.js, который должен находится в папке wp-content/моя_тема/scripts будет таким:
jQuery(document).ready(function ($) { 'use strict'; 'esversion: 6'; // Функция отправки форм. $('.wplb_holder').on('submit', 'form', function (ev) { // Определяем какую форму пользователь заполнил. let this_is = $(this); // Определяем кнопку. let button = $(this).find('input[type="submit"]'); // Определяем тип формы. let type = $(this).attr('data-type'); // Отправляем запрос Ajax в WordPress. $.ajax({ // Путь к файлу admin-ajax.php. url: wplb_ajax_obj.ajaxurl, // Создаем объект, содержащий параметры отправки. data: { // Событие к которому будем обращаться. 'action': 'wplb_ajax_request', // Передаём тип формы. 'type': type, // Передаём значения формы. 'content': $(this).serialize(), // Используем nonce для защиты. 'security': wplb_ajax_obj.nonce, // Перед отправкой Ajax в WordPress. beforeSend: function () {} } }) .always(function() { // Выполнять после каждого Ajax запроса. }) .done(function(data) { // Функция для работы с обработанными данными. }) .fail(function(errorThrown) { // Читать ошибки будем в консоли если что-то пойдет не по плану. console.log(errorThrown); }); // Предотвращаем действие, заложенное в форму по умолчанию. ev.preventDefault(); }); });
Давайте проясним некоторые моменты:
Обратите внимание, что используются две директивы:
- use strict – это так называемый «строгом режиме», который заметно ограничивает синтаксис котором можно пользоваться. Благодаря этому можно на 100% быть уверенным, что скрипт будет правильно работать во всех браузерах. Защита от тираннозавров с кривыми ручками. ?
- esversion: 6 означает, что мы используем синтаксис ECMAScript версии 6, а так версия вышла аж в 2015 году, то за совместимость с браузерами сомневаться не приходится. Можно использовать и более новые версии вплоть до 11-ой (Дата релиза: Июнь 2020), но на свой страх и риск. Понижать версию не рекомендуется.
Вы наверное заметили, что используется функция .on(), вот так:
$('.wplb_holder').on('submit', 'form', function (event) {});
Вместо простой и привычной:
$( "form" ).submit(function( event ) {});
Дело в том, что функция .on() позволяет обращаться к динамически добавленным в DOM (объектная модель документа) элементам.
Если представить, что в результате какого-то события на странице появился новый блочный элемент с ссылкой:
<div id="wplb_new_element"> <a href="#" id="wplb_read_more">Читать дальше..</a> </div>
Если по ссылке нужно будет кликнуть, то:
// Так работать не будет: $('#wplb_read_more').click(function(event){}); // Так будет: $('#wplb_new_element').on('click', '#wplb_read_more', function (event) {});
Конструкция самой $.ajax({}) функции достаточно проста, а для каждой строки мы добавили комментарии. Но стоит обратить внимание, что мы используем объект wplb_ajax_obj, который создали при инициализации самого скрипта.
Событие, которое будет обрабатывать Ajax в WordPress ядре, в нашем случае называется wplb_ajax_request.
Давайте его создадим.
Событие обработки Ajax в WordPress
Возвращаемся в functions.php добавляем следующий код:
// Создаём событие обработки Ajax в WordPress теме. add_action( 'wp_ajax_nopriv_wplb_ajax_request', 'wplb_ajax_request' ); //add_action( 'wp_ajax_wplb_ajax_request', 'wplb_ajax_request' ); // Описываем саму функцию. function wplb_ajax_request() { // Перемененная $_REQUEST содержит все данные заполненных форм. if ( isset( $_REQUEST ) ) { // Проверяем nonce, а в случае если что-то пошло не так, то прерываем выполнение функции. if ( !wp_verify_nonce( $_REQUEST[ 'security' ], 'wplb-nonce' ) ) { wp_die( 'Базовая защита не пройдена' ); } // Введём переменную, которая будет содержать массив с результатом отработки события. $result = array( 'status' => false, 'content' => false ); // Создаём массив который содержит значения полей заполненной формы. parse_str( $_REQUEST[ 'content' ], $creds ); switch ( $_REQUEST[ 'type' ] ) { case 'registration': /** * Заполнена форма регистрации. */ break; case 'authorization': /** * Заполнена форма авторизации. */ break; } // Конвертируем массив с результатами обработки и передаем его обратно как строку в JSON формате. echo json_encode( $result ); } // Заканчиваем работу Ajax. wp_die(); }
Для создания самого события используется хук «wp_ajax_action_name», где action_name это название события, в нашем случае wplb_ajax_request, а вот префикса может быть два:
- wp_ajax_nopriv_wplb_ajax_request, событие будет доступно только для не авторизированных пользователей (гости).
- wp_ajax_wplb_ajax_request – только для авторизированных пользователей.
Получается, что если нам нужен Ajax который будет работать как для гостей, так и для авторизированных пользователей WordPress сайта, то нужно создать оба события одновременно! ?
Мы так же ввели переменную $result, которая будет содержать массив с результатами обработки, а сам массив конвертируем в строку JSON формата и отправляем обратно в браузер.
Пора начинать работать с пользователями.
Регистрация пользователей
При отправки формы, благодаря функции serialize(), в глобальную переменную $_REQUEST и как элемент массива, запишутся все данные заполненной формы.
Начнем с формы регистрации, а значит там где мы используем оператор switch нас интересует случай «registration».
Вставляем следующий код:
case 'registration': /** * Заполнена форма регистрации. */ // Пробуем создать объект с пользователем. $user = username_exists( $creds[ 'wplb_login' ] ); // Проверяем, а может быть уже есть такой пользователь if ( !$user && false == email_exists( $creds[ 'wplb_email' ] ) ) { // Пользователя не существует. // Создаём массив с данными для регистрации нового пользователя. $user_data = array( 'user_login' => $creds[ 'wplb_login' ], // Логин. 'user_email' => $creds[ 'wplb_email' ], // Email. 'user_pass' => $creds[ 'wplb_password' ], // Пароль. 'display_name' => $creds[ 'wplb_login' ], // Отображаемое имя. 'role' => 'subscriber' // Роль. ); // Добавляем пользователя в базу данных. $user = wp_insert_user( $user_data ); // Проверка на ошибки. if ( is_wp_error( $user ) ) { // Невозможно создать пользователя, записываем результат в массив. $result[ 'status' ] = false; $result[ 'content' ] = $user->get_error_message(); } else { // Создаём массив для авторизации. $creds = array( 'user_login' => $creds[ 'wplb_login' ], // Логин пользователя. 'user_password' => $creds[ 'wplb_password' ], // Пароль пользователя. 'remember' => true // Запоминаем. ); // Пробуем авторизовать пользователя. $signon = wp_signon( $creds, false ); if ( is_wp_error( $signon ) ) { // Авторизовать не получилось. $result[ 'status' ] = false; $result[ 'content' ] = $signon->get_error_message(); } else { // Авторизация успешна, устанавливаем необходимые куки. wp_clear_auth_cookie(); clean_user_cache( $signon->ID ); wp_set_current_user( $signon->ID ); wp_set_auth_cookie( $signon->ID ); update_user_caches( $signon ); // Записываем результаты в массив. $result[ 'status' ] = true; } } } else { // Такой пользователь уже существует, регистрация не возможна, записываем данные в массив. $result[ 'status' ] = false; $result[ 'content' ] = esc_html__( 'Пользователь уже существует', 'wplb_ajax_lesson' ); } break;
Всё достаточно просто. При благоприятном стечении обстоятельств пользователь будет зарегистрирован и авторизован, а в противном случае, благодаря встроенному в WordPress обработчику ошибок, мы будем знать, что именно пошло не так.
Проще говоря, результат обработки вернется в файл wplb-ajax.js в 100% случаях.
Давайте посмотрим, что можно сделать с полученным назад данными.
Авторизация пользователя
Мы еж описали процесс авторизации в блоке относящемся к регистрации, а так плодить запросы Ajax в WordPress мы не собираемся, то просто скопируем кусочек кода и вставим его в нужное место:
case 'authorization': /** * Заполнена форма авторизации. */ // Создаём массив для авторизации $creds = array( 'user_login' => $creds[ 'wplb_login' ], // Логин пользователя 'user_password' => $creds[ 'wplb_password' ], // Пароль пользователя 'remember' => true // Запоминаем ); // Пробуем авторизовать пользователя. $signon = wp_signon( $creds, false ); if ( is_wp_error( $signon ) ) { // Авторизовать не получилось $result[ 'status' ] = false; $result[ 'content' ] = $signon->get_error_message(); } else { // Авторизация успешна, устанавливаем необходимые куки. wp_clear_auth_cookie(); clean_user_cache( $signon->ID ); wp_set_current_user( $signon->ID ); wp_set_auth_cookie( $signon->ID ); update_user_caches( $signon ); // Записываем результаты в массив. $result[ 'status' ] = true; } break;
Внимание
Дублирование процедур в коде – это очень плохое решение и вам стоит создать отдельную функцию, описывающую процесс авторизации и вызывать её в нужных местах.
На этом процесс обработки входных данных закачивается, давайте вернёмся в JavaScript файл и поработаем с данными которые вернуться.
Визуализация вернувшихся данных
Прежде чем, что-то сделать с данными которые мы обработали и вернули обратно, давайте посмотрим что можно сделать перед изначальной их отправкой.
Описываем функцию beforeSend: function () {}):
// Перед отправкой запроса Ajax в WordPress ядро. beforeSend: function () { // Спрячем кнопку и покажем пользователю, что скрипт работает. button.hide(); this_is.find('.wplb_alert').hide(); this_is.find('.wplb_loading').show(); }
Всё просто, мы спрятали кнопку отправки формы и показали всевдоспинер, для визуализации процесса.
Теперь опишем процесс визуализации вернувшихся данных:
.done(function(data) { // Функция для работы с обработанными данными. // Переменная $reslut будет хранить результат обработки. let $result = JSON.parse(data); // Проверяем какой статус пришел if($result.status == false){ //Пришла ошибка, скрываем не нужные элементы и возвращаем кнопку. this_is.find('.wplb_alert').addClass('wplb_alert_error').html($result.content).show(); button.show(); }else{ // Пользователь авторизован, покажем ему сообщение. $('.wplb_holder').addClass('wplb_alert wplb_signon').html('<p style="margin-bottom:3px;"><strong>Добро пожаловать!</strong></p>Ajax выполнил свою работу, вы в системе! Перезагрузите страницу и убедитесь.'); } })
Так как код очень простой и содержит комментарии, то описывать его смысла нет.
Послесловие и исходный код
Как видите использовать Ajax в WordPress очень просто, но учтите, что в рамках этого урока мы опустили несколько важных моментов и предлагаем вам разобраться с ними самостоятельно:
- Автоматическая генерация пароля или второе поле для его ввода.
- Отправка уведомления о регистрации нового пользователя со всеми данными для авторизации.
- Реализация процесса выхода.
- Реализация процесса восстановления или сброса пароля.
К этому уроку мы подготовили все исходники, а форму обернули в шорткод для более удобного использования. Скачать можно тут.
Инструкция:
- Содержимое файла functions.php из архива добавьте в конец одноименного файла (functions.php) вашей темы.
- Скопируйте файл wplb_ajax_template.php в коревую папку вашей WordPress темы.
- В корневой папке вашей темы создайте папку scripts и положите туда файл wplb-ajax.js
Вставьте этот шорткод в тело страницы, любым удобным методом, удалив лишние пробелы:
[ wplb_ajax_example ]
Если у вас есть вопросы спрашивайте в комментариях.
Спасибо.
1 комментарий
Отлично, спасибо!