Ошибка 400 (Bad request) при работе виджета через AJAX

103
11 января 2022, 20:40

Возможно, тема уже избитая, но всё же...

Есть такой плагин:

define('PLUGIN_DIR', plugin_dir_path(__FILE__));
include 'AtWidget.php';
class AjaxTest
{
    private $textRes;
    public function AjaxTest()
    {
    }
    // End Widget
    public function add_ajax_action()
    {        
        add_action('wp_ajax_nopriv_testajaxaction', array(
            &$this,
            'test_ajax_action'
        ));
    }
    public function test_ajax_action()
    {
        echo "It's working!";
        wp_die();
    }
    public function test_ajax_widget_registration()
    {
        add_action("widgets_init", function () {
            register_widget("AtWidget");
        });
    }
}
$instance = new AjaxTest();
$instance->add_ajax_action();
$instance->test_ajax_widget_registration();

И виджет к нему:

class AtWidget extends WP_Widget
{
    public function __construct()
    {
        parent::__construct("at_widget", "Тестовый виджет для Ajax на сайте", array(
            “description” => "Тестовый виджет для Ajax на сайте"
        ));
    }
    public function widget($args, $instance)
    {
        $title = $instance[“title”];
        ?>
<script type="text/javascript">
            function SendTestAjaxRequest()
            {                
                    var caNonce = document.getElementById('ca_nonce_test_ajax').value;
                    var ajaxurl ="http://wptest/wp-admin/admin-ajax.php";
                    var data ={action: 'testajaxaction', ca_nonce_: caNonce};
                    $.post(ajaxurl,data , function (data) {
                        alert(data);
                    });
            }
        </script>
<form onSubmit="return false;">
        <?php wp_nonce_field('test-ajax-action', 'ca_nonce_test_ajax'); ?>
            <input type="submit" id="test_at_widget_submit"
        name="test_at_widget_submit" onclick="SendTestAjaxRequest()"
        value="Test">
</form>
<?php
    }
}

Вроде всё делаю по документации, но почему-то всё равно получается ошибка 400. Где я ошибся?

P.S. Использую OpenServer. Виджет находится на сайте. Не в админке.

Answer 1

Вот полностью рабочий код (поместил его как файл в папку mu-plugins).

Здесь главное - два хука: wp_ajax_testajaxaction и wp_ajax_nopriv_testajaxaction.

<?php
class AtWidget extends WP_Widget {
    public function __construct() {
        parent::__construct( "at_widget", "Тестовый виджет для Ajax на сайте", [
            'description' => "Тестовый виджет для Ajax на сайте",
        ] );
    }
    public function widget( $args, $instance ) {
        $title = isset( $instance[ 'title' ] ) ? $instance[ 'title' ] : '';
        ?>
        <script type='text/javascript' src='/wp-includes/js/jquery/jquery.js?ver=1.12.4-wp'></script>
        <script type="text/javascript">
            function SendTestAjaxRequest() {
                var caNonce = document.getElementById( 'ca_nonce_test_ajax' ).value;
                var ajaxurl = "<?php echo admin_url( 'admin-ajax.php' ); ?>";
                var data    = { action: 'testajaxaction', ca_nonce_: caNonce };
                jQuery.post( ajaxurl, data, function( data ) {
                    alert( data );
                } );
            }
        </script>
        <form onSubmit="return false;">
            <?php wp_nonce_field( 'test-ajax-action', 'ca_nonce_test_ajax' ); ?>
            <input type="submit" id="test_at_widget_submit"
                   name="test_at_widget_submit" onclick="SendTestAjaxRequest()"
                   value="Test">
        </form>
        <?php
    }
}
class AjaxTest {
    private $textRes;
    // End Widget
    public function add_ajax_action() {
        add_action( 'wp_ajax_nopriv_testajaxaction', [ $this, 'test_ajax_action' ] );
        add_action( 'wp_ajax_testajaxaction', [ $this, 'test_ajax_action' ] );
    }
    public function test_ajax_action() {
        echo "It's working!";
        exit();
    }
    public function test_ajax_widget_registration() {
        add_action( "widgets_init", function () {
            register_widget( "AtWidget" );
        } );
    }
}
$instance = new AjaxTest();
$instance->add_ajax_action();
$instance->test_ajax_widget_registration();
Answer 2

Короче, всё-таки разобрался сам.

Дело оказалось в том, что хуки wp_ajax_nopriv работают только если пользователь не залогинен. А, пытаюсь отправить запрос с сайта будучи залогинен. Поэтому ничего и не работало.

Чтобы AJAX запрос работал во всех случаях нужно ставить сразу два хука.

public function add_ajax_action()
{        
    add_action('wp_ajax_testajaxaction', array(
        &$this,
        'test_ajax_action'
    ));
    add_action('wp_ajax_nopriv_testajaxaction', array(
        &$this,
        'test_ajax_action'
    ));
}

К сожалению, в документации об этом написано не совсем ясно. Но, тем не менее...

READ ALSO
Как обратиться к последнему элементу mysqli_fetch_assoc

Как обратиться к последнему элементу mysqli_fetch_assoc

Я хотел бы обратиться к последнему элементу в цикле while, чтобы не добавлять табуляцию в кодеЯ бы мог сделать ещё один запрос к БД(на длину таблицы),...

85
Нужна помощь в php с PHPExcel

Нужна помощь в php с PHPExcel

Есть php код, который получает данные из файла sxlsx используя библиотеку PHPExcel, и выводит их в таблицу для печати ценников с qr-кодами

99
Не находит страницу, которая есть. Symfony

Не находит страницу, которая есть. Symfony

Проект на Symfony, я указываю ссылку на страницу, она лежит в проекте, но сайт протестует и выдает 404 ошибку(ссылка указана правильно)

183
Парсер данных с текста

Парсер данных с текста

Спарсил заказы с почты, они в основном в одном формате

108