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(), как описано выше.
Sin
Вы пытаетесь использовать is_page() внутри ajax_login() или внутри ajax_login_init()? Первый вариант не сработает, потому что это Ajax-контекст.
swissspidy
Я перечислил файлы, в которых находятся функции, в описательном тексте выше. Функция is_page() используется в functions.php и служит для включения файла с ajax-функциями только тогда, когда это необходимо.
Sin
Если кто-то использует объектно-ориентированный подход и сталкивается с проблемой 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)?
butlerblog
