Коротка відповідь: AJAX у WordPress дозволяє JavaScript обмінюватися даними з сервером без перезавантаження сторінки. Класичний спосіб: надіслати запит на admin-ajax.php з назвою action, і WordPress виконає PHP-функцію, прив’язану до хука wp_ajax_{action} (для авторизованих користувачів) або wp_ajax_nopriv_{action} (для відвідувачів). Функція повертає JSON, а скрипт оновлює сторінку. Сучасна альтернатива: власний ендпоінт REST API.
Розберемо все покроково, так, як досвідчений розробник пояснює стажеру: спершу ідея, потім мінімальний робочий приклад, потім безпека і наприкінці помилки, на які йде найбільше часу.
Що таке AJAX і навіщо він у WordPress?
AJAX розшифровується як Asynchronous JavaScript and XML, але сьогодні XML ніхто не надсилає. Ви відправляєте запит у фоні, отримуєте JSON і змінюєте частину сторінки. Типові випадки: живий пошук, кнопка «Завантажити ще», фільтрація товарів, відправлення форми без перезавантаження, голосування або лайк запису.
WordPress потрібна стандартна точка входу для таких запитів, бо PHP-код вашої теми чи плагіна не виконується, поки WordPress не завантажений. Ця точка входу: wp-admin/admin-ajax.php.
Як працює AJAX у WordPress?
- Браузер виконує JavaScript і надсилає POST-запит на
admin-ajax.phpз полемaction. - WordPress завантажується, перевіряє значення
actionі запускає відповідний хук:wp_ajax_my_actionдля авторизованих користувачів абоwp_ajax_nopriv_my_actionдля відвідувачів. - Ваша PHP-функція виконується, перевіряє безпеку, робить роботу і повертає JSON через
wp_send_json_success()абоwp_send_json_error(). Ці функції також зупиняють виконання скрипта. - JavaScript отримує JSON і оновлює DOM.
Пастка для стажера: action це просто рядок, який ви вигадуєте самі. Це не назва функції WordPress. Якщо рядок у JavaScript і в add_action() відрізняється хоча б одним символом, нічого не спрацює.
Мінімальний приклад AJAX у WordPress
Зробимо невеликий живий пошук, який повертає заголовки підходящих записів. Він складається з трьох частин: підключити скрипт і передати йому адресу AJAX та nonce, обробити запит у PHP і викликати його з JavaScript.
Крок 1: підключіть скрипт і передайте адресу AJAX
На фронтенді WordPress не надає глобальної змінної ajaxurl, тому передайте її самі через wp_localize_script(). Додайте це у functions.php теми або в плагін:
add_action( 'wp_enqueue_scripts', function () {
wp_enqueue_script(
'my-ajax',
get_template_directory_uri() . '/js/my-ajax.js',
array(),
'1.0',
true
);
wp_localize_script( 'my-ajax', 'myAjax', array(
'url' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( 'my_ajax_nonce' ),
) );
} );
Крок 2: напишіть PHP-обробник
Зареєструйте одну функцію і для авторизованих користувачів, і для відвідувачів. Спершу перевірте nonce, потім очистіть вхідні дані, потім виконайте роботу:
add_action( 'wp_ajax_my_action', 'my_ajax_handler' );
add_action( 'wp_ajax_nopriv_my_action', 'my_ajax_handler' );
function my_ajax_handler() {
check_ajax_referer( 'my_ajax_nonce', 'nonce' );
$term = isset( $_POST['term'] ) ? sanitize_text_field( wp_unslash( $_POST['term'] ) ) : '';
if ( '' === $term ) {
wp_send_json_error( array( 'message' => 'Empty search term' ), 400 );
}
$query = new WP_Query( array(
's' => $term,
'posts_per_page' => 5,
'post_status' => 'publish',
) );
$items = array();
foreach ( $query->posts as $post ) {
$items[] = array(
'title' => get_the_title( $post ),
'url' => get_permalink( $post ),
);
}
wp_send_json_success( $items );
}
Крок 3: викличте його з JavaScript через fetch
Надішліть action, nonce і ваші дані як дані форми. Тіло URLSearchParams саме виставляє потрібний тип вмісту:
const form = document.querySelector('#search-form');
const list = document.querySelector('#results');
form.addEventListener('submit', async (event) => {
event.preventDefault();
const body = new URLSearchParams({
action: 'my_action',
nonce: myAjax.nonce,
term: form.elements.term.value,
});
const response = await fetch(myAjax.url, { method: 'POST', body });
const json = await response.json();
if (!json.success) {
console.error(json.data.message);
return;
}
list.replaceChildren(
...json.data.map((item) => {
const li = document.createElement('li');
const a = document.createElement('a');
a.href = item.url;
a.textContent = item.title;
li.append(a);
return li;
})
);
});
Зверніть увагу: заголовки додаються через textContent, а не innerHTML. Ніколи не вставляйте дані із сервера на сторінку як сирий HTML, якщо ви їх не екранували.
Той самий запит на jQuery
Старі теми досі користуються jQuery. Ідея та сама, змінюється лише синтаксис. Для нового коду jQuery не потрібен:
jQuery.post( myAjax.url, {
action: 'my_action',
nonce: myAjax.nonce,
term: 'wordpress'
} ).done( function ( response ) {
console.log( response.data );
} );
Що можна зробити через AJAX у WordPress?
- Живий пошук. Приклад вище, плюс debounce, щоб не надсилати запит на кожну літеру.
- «Завантажити ще» і пагінація. Надсилаєте номер сторінки, виконуєте
WP_Queryзpagedі повертаєте наступні записи. - Фільтри. Надсилаєте вибрані категорії чи атрибути й повертаєте відфільтрований список, наприклад у магазині на WooCommerce.
- Форми. Відправляєте дані, не залишаючи сторінку, і показуєте повідомлення про успіх.
- Вхід, голосування й лайки. Невеликі дії, що оновлюють один елемент.
Для «Завантажити ще» змінюються лише дані, які ви надсилаєте, і запит, який виконуєте:
$paged = isset( $_POST['page'] ) ? absint( $_POST['page'] ) : 1;
$query = new WP_Query( array(
'post_status' => 'publish',
'posts_per_page' => 6,
'paged' => $paged,
) );
Як захистити AJAX-запити?
Кожен AJAX-обробник це відкриті двері у ваш сайт, тому ставтеся до нього відповідно. Чотири правила покривають більшість випадків:
- Перевіряйте nonce через
check_ajax_referer(). Він захищає від підроблених запитів. Це не авторизація, а на кешованій сторінці nonce може прострочитися. - Перевіряйте права через
current_user_can()для всього, що змінює дані або показує приватну інформацію. - Очищуйте вхідні дані функціями на кшталт
sanitize_text_field()іabsint(), а вивід екранувати. - Не реєструйте хук
noprivдля дій, які мають виконувати лише авторизовані користувачі. Якщо дія редагує чи видаляє щось, вона не повинна бути доступна відвідувачам.
AJAX чи REST API: що обрати?
admin-ajax.php досі працює і підходить для невеликих завдань у темах і плагінах. REST API краще для нового коду, який можуть викликати інші застосунки, для запитів, що кешуються, і для чистіших адрес та перевірок прав. Практична різниця: кожен виклик admin-ajax.php завантажує все середовище WordPress, тому на важкому сайті він може бути повільним.
REST-маршрут для того самого пошуку виглядає так. Зверніть увагу: permission_callback обов’язковий, і для публічного ендпоінта його задають явно:
add_action( 'rest_api_init', function () {
register_rest_route( 'myplugin/v1', '/search', array(
'methods' => 'GET',
'callback' => 'my_rest_search',
'permission_callback' => '__return_true',
'args' => array(
'term' => array(
'required' => true,
'sanitize_callback' => 'sanitize_text_field',
),
),
) );
} );
| admin-ajax.php | REST API | |
|---|---|---|
| Найкраще для | Простих дій у темі чи плагіні | Нових функцій, публічних або кешованих даних, зовнішніх застосунків |
| Безпека | Nonce і ваші власні перевірки | Nonce (X-WP-Nonce) і permission_callback |
| Швидкість | Щоразу завантажує весь WordPress | Також завантажує WordPress, але GET-запити легше кешувати |
| Адреса | Одна адреса для всього | Окрема адреса для кожного маршруту |
Чому AJAX-запит у WordPress не працює?
Відкрийте інструменти розробника в браузері, перейдіть на вкладку Network і подивіться на запит до admin-ajax.php. Код статусу й відповідь підкажуть більшість того, що потрібно:
| Симптом | Імовірна причина | Що перевірити |
|---|---|---|
Відповідь 0 зі статусом 200 | Обробник виконався, але не зупинив скрипт | Завершіть обробник через wp_send_json_success(), wp_send_json_error() або wp_die() |
Відповідь 0 зі статусом 400 | Для цього action не зареєстровано хук, або action відсутній | Точно співставте рядок action і додайте хук wp_ajax_nopriv_ для відвідувачів |
-1 або статус 403 | Перевірку nonce не пройдено, або запит заблокував плагін безпеки чи файрвол | Перевірте назву nonce, оновіть кешовані сторінки й подивіться правила плагіна безпеки |
myAjax is not defined | Скрипт не підключено або не передано дані | Перевірте handle у wp_enqueue_script() і wp_localize_script() |
| Код обробника не виконується | Код пропускається під час AJAX-запитів | admin-ajax.php вважається адмінкою, тому код в умові ! is_admin() не завантажиться |
Якщо запити повільні, подивіться, що робить обробник: важкі запити, зовнішні виклики та плагіни, що завантажуються на кожен запит. Про загальне прискорення читайте в матеріалі «Оптимізація швидкості сайту».
Часті запитання
Що таке admin-ajax.php у WordPress?
Це файл, який WordPress надає для обробки AJAX-запитів. Він завантажує WordPress, читає параметр action і виконує PHP-функцію, зареєстровану для нього.
У чому різниця між wp_ajax і wp_ajax_nopriv?
wp_ajax_{action} виконується для авторизованих користувачів, а wp_ajax_nopriv_{action} для відвідувачів без входу. Щоб підтримати обох, зареєструйте функцію на обох хуках.
Як отримати адресу AJAX на фронтенді?
Передайте її з PHP через wp_localize_script(), використавши admin_url( 'admin-ajax.php' ), як у прикладі вище. Не покладайтеся на глобальну змінну ajaxurl поза адмінкою.
Чи застарів admin-ajax.php?
Ні, він і далі підтримується. Для нових функцій, які можуть використовувати інші застосунки, зазвичай краще підходить REST API.
Чи потрібен jQuery для AJAX у WordPress?
Ні. Метод fetch() у браузері працює добре, а jQuery потрібен лише якщо ваша тема чи плагін уже від нього залежить.
Чи безпечний AJAX у WordPress?
Так, якщо перевіряти nonce, права, очищувати вхідні дані й екранувати вивід. AJAX-обробник без цих перевірок становить ризик для безпеки.
Потрібна допомога з розробкою на WordPress?
Якщо вам потрібні кастомні функції, теми на WordPress або розробка сайту під ключ, опишіть задачу в кілька речень, і я відповім із запитаннями та орієнтиром. Telegram: t.me/dykyiivan, пошта: dykyiivan@outlook.com.
Обговорити проєкт