Неверный запрос 400… jQuery ajax пост json данных в wordpress admin-ajax.php

Вопрос или проблема

Я пытался, пытался и пытался, я искал и искал… Я не могу понять, почему это не работает. Одна большая проблема в том, что я не могу выяснить, как получить хорошую информацию для отладки о том, почему это не удается.

В любом случае, у меня есть поле поиска для поиска библиотек на CDNJS.com (что работает). При выборе результата я хочу добавить данные этой библиотеки в свою пользовательскую таблицу WordPress. Этот процесс не удается, независимо от того, что я пробую.

Вот код:

<?php

    function cdnjs_add_library_callback() {
        // Получаем данные библиотеки из POST-запроса
        $library = json_decode(file_get_contents('php://input'), true);

        // Вставляем библиотеку в таблицу "cdnjs_libraries"
        global $wpdb;
        $table_name = $wpdb->prefix . 'cdnjs_libraries';
        $wpdb->insert(
            $table_name,
            array(
                'description' => $library['description'],
                'homepage' => $library['homepage'],
                'latest' => $library['latest'],
                'license' => $library['license'],
                'name' => $library['name'],
                'version' => $library['version']
            )
        );

        // Проверяем на наличие ошибок
        if ($wpdb->last_error) {
            die("Ошибка при вставке библиотеки: " . $wpdb->last_error);
        }

        // Возвращаем сообщение об успехе
        echo "Библиотека успешно добавлена";

        wp_die(); // это необходимо для немедленного завершения и возврата правильного ответа
    }
    add_action( 'wp_ajax_cdnjs_add_library', 'cdnjs_add_library_callback' );

?>

    <div class="wrap">
        <h1>Менеджер библиотек CDNJS</h1>
        <p>&nbsp;</p>
        <div id="search-form">
            <form onsubmit="return false;">
                <h2><label for="library-search">Поиск CDNJS</label></h2>
                <input type="text" id="library-search" name="library-search" placeholder="Начните вводить для поиска..." size=30>
            </form>
        </div>
        <p>&nbsp;</p>
        <h2>Управляемые библиотеки</h2>
        <table id="managed-libraries" class="wp-list-table widefat fixed striped">
            <thead>
                <tr>
                    <th>Действие</th>
                    <th>Имя файла</th>
                    <th>Описание</th>
                    <th>Версия</th>
                    <th>Лицензия</th>
                    <th>Домашняя страница</th>
                    <th>Удалить</th>
                </tr>
            </thead>
            <tbody>
                <?php echo generate_table_rows($managed_libraries); ?>
            </tbody>
        </table>
    </div>

    <script>
    jQuery(document).ready(function($) {

        // Настраиваем поле поиска как поле автозаполнения
        $("#library-search").autocomplete({
            // Устанавливаем источник параметров автозаполнения на API CDNJS
            source: function(request, response) {
                $.ajax({
                    data: {
                        search: request.term,
                        fields: "name,description,version,license,homepage"
                    },
                    success: function(results) {
                        console.log(results);
                        // Извлекаем список названий библиотек, описаний и URL из 
                        // результатов и передаем их в коллбек ответа
                        var libraries = results.results.map(function(library) {
                            return {
                                label: "<b>"+library.name+"</b><br><i>"+library.description+"</i>",
                                value: library
                            };
                        });
                        response(libraries);
                    },
                    url: "https://api.cdnjs.com/libraries"
                });
            },
            minLength: 3,
            select: function(event, ui) {
                // Когда библиотека выбрана из списка автозаполнения,
                // добавляем эту библиотеку в таблицу "cdnjs_libraries" с помощью 
                // выполнения AJAX POST-запроса к PHP действию "cdnjs_add_library"

                // Получаем выбранный объект библиотеки
                var library = ui.item.value;

                // Выполняем AJAX-запрос к действию "cdnjs_add_library"
                $.ajax({
                    url: ajaxurl,
                    type: 'POST',
                    dataType: 'json',
                    contentType: 'application/json; charset=utf-8',
                    data: JSON.stringify({
                        action: 'cdnjs_add_library',
                        library: library
                    }),
                    success: function(response) {
                        console.log(response);
                        // Добавляем библиотеку в таблицу управляемых библиотек
                        $("#managed-libraries tbody").append(generateTableRow(library));
                    },
                    error: function(error) {
                        console.log(error);
                    }
                });
            }
        }).autocomplete( "instance" )._renderItem = function( ul, library ) {
            // Настраиваем отображение параметров автозаполнения
            // Создаем новый элемент списка для библиотеки
            var listItem = $("<li>");
            // Создаем ссылку на библиотеку
            var libraryLink = $("<a>", {
                href: library.url,
                target: "_blank",
                html: library.label
            });
            // Добавляем ссылку в элемент списка
            listItem.append(libraryLink);
            // Возвращаем элемент списка
            return listItem.appendTo(ul);
        };


    });
    </script>

Чтобы уточнить мои комментарии, ваша проблема здесь:

contentType: 'application/json; charset=utf-8',
data: JSON.stringify({
    action: 'cdnjs_add_library',
    library: library
}),

При отправке данных на admin-ajax.php, вам нужно установить свойство action в data на имя действия, например, cdnjs_add_library. Вы этого не делаете здесь. data не является объектом с свойством action, как и ожидается, это строка, содержащая JSON, который случайно включает свойство action. Это не одно и то же.

В исходном коде admin-ajax.php вы увидите это:

$action = $_REQUEST['action'];

Если вы отправляете JSON на admin-ajax.php, $_REQUEST не будет иметь свойства action, по причинам, которые я объясняю здесь. Это означает, что ваше действие не будет выполнено, и ваш PHP-код не будет запущен.

Решение заключается в том, чтобы убрать contentType и передать данные вот так:

data: {
    action: 'cdnjs_add_library',
    library: library
},

Ваша функция cdnjs_add_library_callback() тогда должна установить $libary следующим образом:

$library = $_POST['library'];

Ответ или решение

Ошибка 400 Bad Request при отправке JSON данных в admin-ajax.php WordPress

Проблема, с которой вы столкнулись, связана с некорректной отправкой данных в admin-ajax.php вашего WordPress сайта, что, в свою очередь, вызывает ошибку 400 (Bad Request). Давайте разберёмся подробнее, что происходит, и как это исправить.

В чем проблема?

Когда вы используете jQuery для выполнения AJAX-запроса на admin-ajax.php, важно правильно формировать данные, которые будете отправлять. В вашем коде вы используете следующий фрагмент для отправки данных:

contentType: 'application/json; charset=utf-8',
data: JSON.stringify({
    action: 'cdnjs_add_library',
    library: library
}),

Здесь вы устанавливаете contentType в application/json, и формируете данные как JSON-строку. Однако в admin-ajax.php ожидается получение данных в формате application/x-www-form-urlencoded или multipart/form-data, что является стандартом для отправки POST-запросов в WordPress. Когда данные отправляются в формате JSON, это приводит к тому, что PHP не может разобрать их, и вы не получаете переменную $_REQUEST['action'], что вызывает ошибку 400.

Как исправить проблему?

Для того чтобы ваша функция обработчика сработала корректно, вам нужно изменить способ передачи данных. Вместо того, чтобы сериализовать данные в JSON, отправьте их как объект:

$.ajax({
    url: ajaxurl,
    type: 'POST',
    data: {
        action: 'cdnjs_add_library',
        library: library
    },
    success: function(response) {
        console.log(response);
        // Обновление таблицы управляемых библиотек
        $("#managed-libraries tbody").append(generateTableRow(library));
    },
    error: function(error) {
        console.log(error);
    }
});

В этом случае сервер получит данные в формате, который он ожидает. Ваш серверный код также нужно немного изменить:

Обновите функцию обработчика PHP

Теперь вам нужно будет изменить, как вы получаете данные в вашем PHP обработчике:

function cdnjs_add_library_callback() {
    // Получаем данные библиотеки из массива POST
    $library = $_POST['library'];

    // Проверяем, что переменная существует и не пуста
    if (empty($library)) {
        wp_send_json_error('Недостаточно данных для добавления библиотеки.'); // Возвращаем ошибку
    }

    // Извлекаем данные из массива библиотеки
    global $wpdb;
    $table_name = $wpdb->prefix . 'cdnjs_libraries';
    $wpdb->insert(
        $table_name,
        array(
            'description' => $library['description'],
            'homepage'    => $library['homepage'],
            'latest'      => $library['latest'],
            'license'     => $library['license'],
            'name'        => $library['name'],
            'version'     => $library['version']
        )
    );

    // Проверяем на наличие ошибок
    if ($wpdb->last_error) {
        wp_send_json_error("Ошибка при добавлении библиотеки: " . $wpdb->last_error);
    }

    // Возвращаем сообщение об успешном добавлении
    wp_send_json_success("Библиотека успешно добавлена");
}
add_action('wp_ajax_cdnjs_add_library', 'cdnjs_add_library_callback');

Вывод

Изменив способ отправки данных и добавив проверку на их наличие, вы сможете устранить ошибку 400 Bad Request при добавлении данных о библиотеках в вашу пользовательскую таблицу WordPress.

Если вы продолжаете сталкиваться с проблемами, рекомендуется использовать инструменты разработчика браузера для отслеживания и просмотра отправляемых запросов и ответов, которые могут дать вам дополнительную информацию о происходящем.

Оцените материал
Добавить комментарий

Капча загружается...