400 bad request в admin-ajax.php при использовании хука wp_enqueue_scripts

17 янв. 2018 г., 12:39:08
Просмотры: 108K
Голосов: 24

Я работал недавно с 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?

1
Комментарии

вы можете ознакомиться с этим обсуждением здесь https://stackoverflow.com/a/66464509/13278193

mod7ex mod7ex
3 мар. 2021 г. 22:44:13
Все ответы на вопрос 4
4
21

Думаю, единственное, чего здесь не хватает, — это вынести 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' ).

17 янв. 2018 г. 12:48:26
Комментарии

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

Sin Sin
17 янв. 2018 г. 13:04:22

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

swissspidy swissspidy
17 янв. 2018 г. 14:05:58

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

Sin Sin
17 янв. 2018 г. 14:48:35

@Sin Again, функция is_page() не работает в контексте Ajax. Я обновил свой ответ соответственно.

swissspidy swissspidy
17 янв. 2018 г. 14:58:22
0

Не забудьте добавить имя функции 'action' к тегу wp_ajax_.

function fetchorderrows() { // Эта функция будет выполняться при AJAX-запросе
  // Здесь можно делать потрясающие вещи весь день
}

add_action('wp_ajax_fetchorderrows', 'fetchorderrows', 0);
14 апр. 2019 г. 23:43:03
1
-1

Если кто-то использует объектно-ориентированный подход и сталкивается с проблемой AJAX 400, возможно, потребуется вынести обработчики AJAX за пределы класса (попробуйте в основном файле плагина) и использовать класс и метод во втором аргументе.

add_action( 'wp_ajax_your_handle', [ 'Class_Name', 'function_name' ] );
add_action( 'wp_ajax_nopriv_your_handle', [ 'Class_Name', 'function_name' ] );
18 нояб. 2020 г. 11:48:31
Комментарии

Нет необходимости выносить их за пределы класса. Просто подключите их к admin_init, чтобы они выполнялись при обработке ajax-запросов.

Erenor Paz Erenor Paz
18 дек. 2020 г. 16:50:41
1
-4

просто напишите die; в конце, как показано ниже...изображение с примером кода

12 нояб. 2018 г. 15:12:27
Комментарии

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

butlerblog butlerblog
12 нояб. 2018 г. 16:46:11