AJAX в WordPress плагинах: реальный пример из практики
- Показывать справа: 0
При разработке плагинов для WordPress AJAX используется практически в каждом более-менее сложном проекте: личные кабинеты, формы, динамический контент, фильтры, действия без перезагрузки страницы.
В этой статье покажу не абстрактный пример, а реальную архитектуру AJAX, которую использую в своих плагинах.
Где применяется AJAX в плагинах
- Личные кабинеты пользователей
- Обработка форм без перезагрузки
- Работа с тарифами, заказами
- Динамическая подгрузка данных
- Интерактивные интерфейсы
Структура вашего плагина
Хорошая практика — организовывать код плагина. Пример такой структуры:
your-plugin-name/
├── your-plugin-name.php (главный файл)
├── lib/
│ ├── ajax.php (класс для базовой обработки AJAX)
│ └── events/
│ ├── ajaxs/ (отдельные файлы для каждого AJAX действия)
│ │ ├── dct_add_rate.php
│ │ └── ...
│ └── ajaxs.php (файл для инклюдов и регистрации)
└── asset/
└── js/
└── script.js
Базовая структура плагина
В главном файле
define('DCT_DIR', WP_PLUGIN_DIR .'/' . str_replace(basename(__FILE__), '', plugin_basename(__FILE__)));
Подключаю библиотеку AJAX:
require_once DCT_DIR . '/lib/ajax.php';
Абстрактный класс для обработки AJAX
Чтобы не дублировать код, используется базовый класс (/lib/ajax.php):
abstract class ajax_hand_dct {
function __construct($action_name) {
$this->init_hooks($action_name);
}
public function init_hooks($action_name) {
add_action('wp_ajax_'.$action_name, array($this,'callback'));
add_action('wp_ajax_nopriv_'.$action_name, array($this,'callback_nopriv'));
}
public function callback_nopriv() {
$this->callback();
}
abstract public function callback();
}
Такой подход позволяет быстро добавлять новые AJAX-обработчики без копирования логики.
Динамическое подключение обработчиков
Подключение файлов по action (/lib/ajaxs.php):
$action = isset($_REQUEST['action']) ? sanitize_text_field($_REQUEST['action']) : '';
$filepath = DCT_DIR . '/lib/events/ajaxs/';
if (is_file($filepath . $action . ".php")) {
require_once $filepath . $action . ".php";
}
Пример реального AJAX обработчика
Этот код находится в файле, например: DCT_DIR . '/lib/events/ajaxs/dct_add_rate.php'
class dct_add_rate extends ajax_hand_dct {
// Не забудьте вызвать конструктор родителя, если он есть,
// или просто создать экземпляр, передав действие.
// Обычно это делается так: new dct_add_rate('dct_add_rate');
// Если конструктор в базовом классе вызывается, как здесь:
function __construct() {
parent::__construct('dct_add_rate'); // 'dct_add_rate' - это значение для 'action' в JS
}
function callback() {
global $wpdb;
// Предполагается, что lib/rate.php содержит нужные классы/функции
// require_once DCT_DIR . 'lib/rate.php';
$status = 1; // 1 - успех, 0 - ошибка
$error = '';
$html = '';
$fled = array(); // Массив для возвращаемых данных (например, ID новой записи)
$mess_fled = array(); // Массив сообщений по конкретным полям
$link = ''; // Ссылка для редиректа
// --- Безопасность: Проверка Nonce ---
// Предполагаем, что nonce передается через POST
if ( !isset( $_POST['_ajax_nonce'] ) || !wp_verify_nonce( $_POST['_ajax_nonce'], 'dct_ajax_nonce_action' ) ) {
wp_send_json_error( array( 'message' => 'Ошибка безопасности: проверьте ваш запрос.' ) );
}
// --- Получение данных ---
$rate_id = isset($_POST['rate_id']) ? intval($_POST['rate_id']) : 0;
// --- Валидация ---
if (empty($rate_id)) {
$status = 0;
$error = 'Не выбран тариф';
}
// --- Проверка авторизации (если требуется) ---
if ( !is_user_logged_in() ) {
// Если действие требует авторизации, но пользователь не вошел
// $status = 0;
// $error = 'Для выполнения этого действия необходима авторизация.';
// Или просто выйти, если это не требуется всегда
// wp_send_json_error( array( 'message' => 'Вы должны быть авторизованы.' ) );
}
if ($status == 1) {
$user = wp_get_current_user();
$user_id = $user->ID;
// здесь основная логика
// Пример: добавление в базу данных
// $result = $wpdb->insert('wp_dct_rates', array('user_id' => $user_id, 'rate_id' => $rate_id, 'timestamp' => current_time('mysql')), array('%d', '%d', '%s'));
// if ($result) {
// $new_row_id = $wpdb->insert_id;
// $fled['new_id'] = $new_row_id;
// $message = 'Тариф успешно добавлен!';
// } else {
// $status = 0;
// $message = 'Ошибка при добавлении тарифа.';
// }
// Пример получения ссылки, если она нужна
// $page_kab_id = DCT::get_option_web('page_kab'); // Пример функции из вашего плагина
// if ($page_kab_id) {
// $link = get_permalink($page_kab_id);
// }
}
// Формируем объект ответа
$options = array(
"fled" => $fled, // Возвращаемые данные
"link" => $link, // Ссылка для редиректа
"mess_fled" => $mess_fled, // Сообщения по полям
"message" => $error, // Общее сообщение (часто используется для ошибок)
"html" => $html, // HTML для вставки на страницу
"status" => $status, // Статус операции
);
// Отправляем JSON ответ.
// wp_send_json_success($options); // Используйте, если все прошло успешно
// wp_send_json_error($options); // Используйте, если произошла ошибка
// В вашем примере была только wp_send_json_success, оставим так,
// но в реальном проекте стоит различать успешные и ошибочные ответы.
// Если $status == 0, лучше использовать wp_send_json_error.
if ($status == 1) {
wp_send_json_success($options);
} else {
wp_send_json_error($options);
}
}
}
// Создание экземпляра класса для регистрации AJAX обработчика.
// Важно, чтобы 'dct_add_rate' совпало с $action в JS и с названием файла.
new dct_add_rate();
Передача переменных в JavaScript
Для передачи PHP-переменных (например, `admin-ajax.php` URL) в JavaScript используется `wp_head` или `wp_localize_script`.
function js_variables_dct(){
echo '<script type="text/javascript">
var ajax_url_web = "'.admin_url('admin-ajax.php').'";
var URL_PAGE = "'.get_permalink().'";
var URL_ASSET = "'.DCT_URL.'asset/";
// Если вам нужен nonce, его также можно передать здесь
// var _ajax_nonce = "'.wp_create_nonce('dct_ajax_nonce_action').'";
</script>';
}
add_action('wp_head','js_variables_dct');
Пример AJAX запроса на стороне JS
Использование `jQuery.ajax` для отправки данных.
// Предполагается, что mdata содержит все необходимые параметры, включая 'action' и nonce.
// Пример:
// var mdata = {
// action: 'dct_add_rate', // Действие, которое соответствует 'wp_ajax_dct_add_rate'
// rate_id: 123,
// _ajax_nonce: _ajax_nonce // Полученный из PHP
// };
jQuery.ajax({
url: ajax_url_web, // Переменная, полученная из PHP
data: mdata, // Данные для отправки
dataType: 'json', // Ожидаем JSON ответ
type: 'POST', // Метод запроса
beforeSend: function() {
// Показываем индикатор загрузки
console.log('Отправка данных...');
// Например: jQuery('#loading-indicator').show();
},
success: function (res) {
console.log('Ответ сервера:', res);
// res будет объектом, содержащим 'success' (boolean) и 'data' (то, что вернул wp_send_json_success/error)
if (res.success) {
// Обработка успешного ответа
if (res.data && res.data.message) {
alert('Успех: ' + res.data.message);
}
if (res.data && res.data.html) {
jQuery('#some-container').html(res.data.html);
}
if (res.data && res.data.link) {
window.location.href = res.data.link; // Перенаправление
}
} else {
// Обработка ошибки
if (res.data && res.data.message) {
alert('Ошибка: ' + res.data.message);
} else {
alert('Произошла неизвестная ошибка.');
}
}
},
error: function(jqXHR, textStatus, errorThrown) {
// Обработка сетевых ошибок или ошибок сервера
console.error('AJAX Error:', textStatus, errorThrown);
alert('Произошла ошибка при выполнении запроса.');
},
complete: function() {
// Действия, выполняемые после завершения запроса (успех или ошибка)
console.log('Запрос завершен.');
// Например: jQuery('#loading-indicator').hide();
}
});
Что важно учитывать
- Всегда валидировать входящие данные на стороне сервера.
- Использовать `sanitize_*` функции для очистки данных.
- Проверять авторизацию пользователя, если действие требует прав.
- Структурировать код: использовать классы, отдельные файлы для каждого AJAX-действия.
- Всегда использовать Nonce для защиты от CSRF-атак.
- Предоставлять обратную связь пользователю (индикаторы загрузки, сообщения об успехе/ошибке).
Разработка и доработка WordPress плагинов
Если вам нужно реализовать подобную архитектуру или разработать плагин под задачи бизнеса:
Разработка на WordPress
Доработка WordPress
Заключение
AJAX — ключевой инструмент современной разработки на WordPress. Грамотная архитектура позволяет масштабировать проект и упрощает поддержку.