400 bad request в admin-ajax.php при использовании хука wp_enqueue_scripts
Я работал недавно с ajax. Учебники, которые вы находите в интернете, все очень похожи и довольно просты в реализации.
Но я всегда получаю bad request 400 в файле ajax-admin.php
.
После долгого и интенсивного поиска я выяснил, что это происходит из-за времени интеграции.
Если я использую хук действия init
для инициализации скрипта и wp_localize_script
, все работает нормально. Значит сам код должен быть правильным.
my-page-test-functions.php
function ajax_login_init(){
wp_register_script('ajax-login-script',get_stylesheet_directory_uri().'/js/ajax-login-script.js',array('jquery'));
wp_enqueue_script('ajax-login-script');
wp_localize_script('ajax-login-script','ajax_login_object',array('ajaxurl' => admin_url('admin-ajax.php'),'redirecturl' => 'REDIRECT_URL_HERE','loadingmessage' => __('Отправка информации пользователя, пожалуйста подождите...')));
add_action('wp_ajax_nopriv_ajaxlogin','ajax_login');
}
if(!is_user_logged_in()){
add_action('init','ajax_login_init');
}
function ajax_login(){
//nonce-поле создается на странице
check_ajax_referer('ajax-login-nonce','security');
//КОД
die();
}
Но если я использую, например, хук действия wp_enqeue_scripts
, я всегда получаю bad request.
if(!is_user_logged_in()){
add_action('wp_enqueue_scripts','ajax_login_init');
}
Проблема в следующем:
Я хотел бы иметь функции в отдельном php файле и загружать их только если они нужны на определенной странице. Для этого мне нужен, например is_page()
.
Но is_page()
работает самое раннее когда я подключаю функцию с include в хук действия parse_query
:
functions.php
function sw18_page_specific_functions(){
if(is_page('page-test')){
include_once dirname(__FILE__).'/includes/my-page-test-functions.php';
}
}
add_action('parse_query','sw18_page_specific_functions');
Таким образом, функции, привязанные к хуку init
в файле my-page-test-functions.php
не срабатывают, я полагаю, потому что init
идет перед parse_query
.
Есть ли лучшие практики организации этого, чтобы все работало? Или как я могу исправить bad request в admin-ajax.php
при использовании хука действия wp_enqeue_scripts
?
Думаю, единственное, чего здесь не хватает, — это вынести add_action('wp_ajax_nopriv_ajaxlogin','ajax_login');
за пределы функции ajax_login_init
.
Этот код регистрирует ваш обработчик Ajax, но если выполнять его только внутри wp_enqueue_scripts
, то это уже слишком поздно, и хуки wp_ajax_nopriv_
уже отработали.
Попробуйте сделать так:
function ajax_login_init(){
if ( ! is_user_logged_in() || ! is_page( 'page-test' ) ) {
return;
}
wp_register_script('ajax-login-script',get_stylesheet_directory_uri().'/js/ajax-login-script.js',array('jquery'));
wp_enqueue_script('ajax-login-script');
wp_localize_script('ajax-login-script','ajax_login_object',array('ajaxurl' => admin_url('admin-ajax.php'),'redirecturl' => 'REDIRECT_URL_HERE','loadingmessage' => __('Отправка данных пользователя, пожалуйста, подождите...')));
}
add_action( 'wp_enqueue_scripts','ajax_login_init' );
add_action( 'wp_ajax_nopriv_ajaxlogin','ajax_login' );
function ajax_login(){
//nonce-поле создается на странице
check_ajax_referer('ajax-login-nonce','security');
//КОД
die();
}
Обновление:
Теперь стало яснее, что вы хотите загружать JavaScript только на конкретной странице. Это значит, что проверку is_page()
нужно поместить внутрь ajax_login_init()
. Я обновил код соответствующим образом.
Почему ваше решение не сработало?
Проверка is_page()
означала, что ваш файл функций загружался только на этой странице. ajax_login_init()
вызывался, и скрипты подключались. Пока всё хорошо.
Теперь ваш скрипт делает ajax-запрос. Как уже упоминалось в комментариях, ajax-запросы не знают, на какой странице вы находитесь. Неспроста файл находится по адресу wp-admin/admin-ajax.php
. Там нет WP_Query
, поэтому is_page()
не работает во время ajax-запроса.
Поскольку это не работает, функция sw18_page_specific_functions()
не делает ничего в контексте ajax. Это значит, что ваш файл функций не загружен, и обработчик ajax не существует.
Вот почему вам нужно всегда включать этот файл функций и перенести проверку is_page()
внутрь ajax_login_init()
.
Вместо sw18_page_specific_functions() { … }
просто выполняйте include_once dirname(__FILE__).'/includes/my-page-test-functions.php';
напрямую. Без вызова add_action( 'parse_query' )
.

Хорошее предложение. Я изменил это (ошибка осталась той же), но проблема в том, что файл с функциями загружается слишком поздно. Однако мне нужно определить, какая страница используется. Сейчас я пытаюсь сделать это с помощью is_page()
, как описано выше.

Вы пытаетесь использовать is_page()
внутри ajax_login()
или внутри ajax_login_init()
? Первый вариант не сработает, потому что это Ajax-контекст.

Я перечислил файлы, в которых находятся функции, в описательном тексте выше. Функция is_page()
используется в functions.php и служит для включения файла с ajax-функциями только тогда, когда это необходимо.

Если кто-то использует объектно-ориентированный подход и сталкивается с проблемой AJAX 400, возможно, потребуется вынести обработчики AJAX за пределы класса (попробуйте в основном файле плагина) и использовать класс и метод во втором аргументе.
add_action( 'wp_ajax_your_handle', [ 'Class_Name', 'function_name' ] );
add_action( 'wp_ajax_nopriv_your_handle', [ 'Class_Name', 'function_name' ] );

Привет, Зи Хан. Добро пожаловать на сайт. Ваш ответ требует некоторых доработок. Во-первых, если ваш ответ — это код, не публикуйте скриншот. Вместо этого разместите код в виде сниппета и отформатируйте его как код (используйте кнопку {}). Вероятно, именно поэтому ваш ответ получил минус и не был принят. Также было бы полезно добавить немного пояснений — например, "почему" просто написать die() и где именно это должно находиться по отношению к коду в оригинальном сообщении (OP)?
