Bad Request 400... jQuery ajax post of json data to wordpress admin-ajax.php

admin2025-01-08  5

I've tried and tried and tried, I've searched and searched... I can't figure out why this isn't working. One huge problem is I can't seem to figure out how to get any good debug info about why this is failing.

Anyway, I have a search field to lookup libraries from CDNJS (which works). Upon selection of a result, I am wanting to add that library data to a custom Wordpress table. That process is failing, no matter what I try.

Here's the code:

<?php

    function cdnjs_add_library_callback() {
        // Get the library data from the POST request
        $library = json_decode(file_get_contents('php://input'), true);

        // Insert the library into the "cdnjs_libraries" table
        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']
            )
        );

        // Check for errors
        if ($wpdb->last_error) {
            die("Error inserting library: " . $wpdb->last_error);
        }

        // Return a success message
        echo "Library added successfully";

        wp_die(); // this is required to terminate immediately and return a proper response
    }
    add_action( 'wp_ajax_cdnjs_add_library', 'cdnjs_add_library_callback' );

?>

    <div class="wrap">
        <h1>CDNJS Library Manager</h1>
        <p>&nbsp;</p>
        <div id="search-form">
            <form onsubmit="return false;">
                <h2><label for="library-search">Search CDNJS</label></h2>
                <input type="text" id="library-search" name="library-search" placeholder="Type to start searching..." size=30>
            </form>
        </div>
        <p>&nbsp;</p>
        <h2>Managed Libraries</h2>
        <table id="managed-libraries" class="wp-list-table widefat fixed striped">
            <thead>
                <tr>
                    <th>Action</th>
                    <th>Filename</th>
                    <th>Description</th>
                    <th>Version</th>
                    <th>License</th>
                    <th>Homepage</th>
                    <th>Delete</th>
                </tr>
            </thead>
            <tbody>
                <?php echo generate_table_rows($managed_libraries); ?>
            </tbody>
        </table>
    </div>

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

        // Set up the search field as an autocomplete field
        $("#library-search").autocomplete({
            // Set the source of the autocomplete options to the CDNJS API
            source: function(request, response) {
                $.ajax({
                    data: {
                        search: request.term,
                        fields: "name,description,version,license,homepage"
                    },
                    success: function(results) {
                        console.log(results);
                        // Extract the list of library names, descriptions, and URLs from 
                        // the results and pass them to the response callback
                        var libraries = results.results.map(function(library) {
                            return {
                                label: "<b>"+library.name+"</b><br><i>"+library.description+"</i>",
                                value: library
                            };
                        });
                        response(libraries);
                    },
                    url: ";
                });
            },
            minLength: 3,
            select: function(event, ui) {
                // When a library is selected from the autocomplete list,
                // add that library to the "cdnjs_libraries" table by 
                // making an AJAX POST call to the "cdnjs_add_library" PHP action

                // Get the selected library object
                var library = ui.item.value;

                // Make an AJAX call to the "cdnjs_add_library" action
                $.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);
                        // Add the library to the table of managed libraries
                        $("#managed-libraries tbody").append(generateTableRow(library));
                    },
                    error: function(error) {
                        console.log(error);
                    }
                });
            }
        }).autocomplete( "instance" )._renderItem = function( ul, library ) {
            // Customize the display of the autocomplete options
            // Create a new list item for the library
            var listItem = $("<li>");
            // Create a link for the library
            var libraryLink = $("<a>", {
                href: library.url,
                target: "_blank",
                html: library.label
            });
            // Append the link to the list item
            listItem.append(libraryLink);
            // Return the list item
            return listItem.appendTo(ul);
        };


    });
    </script>

I've tried and tried and tried, I've searched and searched... I can't figure out why this isn't working. One huge problem is I can't seem to figure out how to get any good debug info about why this is failing.

Anyway, I have a search field to lookup libraries from CDNJS.com (which works). Upon selection of a result, I am wanting to add that library data to a custom Wordpress table. That process is failing, no matter what I try.

Here's the code:

<?php

    function cdnjs_add_library_callback() {
        // Get the library data from the POST request
        $library = json_decode(file_get_contents('php://input'), true);

        // Insert the library into the "cdnjs_libraries" table
        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']
            )
        );

        // Check for errors
        if ($wpdb->last_error) {
            die("Error inserting library: " . $wpdb->last_error);
        }

        // Return a success message
        echo "Library added successfully";

        wp_die(); // this is required to terminate immediately and return a proper response
    }
    add_action( 'wp_ajax_cdnjs_add_library', 'cdnjs_add_library_callback' );

?>

    <div class="wrap">
        <h1>CDNJS Library Manager</h1>
        <p>&nbsp;</p>
        <div id="search-form">
            <form onsubmit="return false;">
                <h2><label for="library-search">Search CDNJS</label></h2>
                <input type="text" id="library-search" name="library-search" placeholder="Type to start searching..." size=30>
            </form>
        </div>
        <p>&nbsp;</p>
        <h2>Managed Libraries</h2>
        <table id="managed-libraries" class="wp-list-table widefat fixed striped">
            <thead>
                <tr>
                    <th>Action</th>
                    <th>Filename</th>
                    <th>Description</th>
                    <th>Version</th>
                    <th>License</th>
                    <th>Homepage</th>
                    <th>Delete</th>
                </tr>
            </thead>
            <tbody>
                <?php echo generate_table_rows($managed_libraries); ?>
            </tbody>
        </table>
    </div>

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

        // Set up the search field as an autocomplete field
        $("#library-search").autocomplete({
            // Set the source of the autocomplete options to the CDNJS API
            source: function(request, response) {
                $.ajax({
                    data: {
                        search: request.term,
                        fields: "name,description,version,license,homepage"
                    },
                    success: function(results) {
                        console.log(results);
                        // Extract the list of library names, descriptions, and URLs from 
                        // the results and pass them to the response callback
                        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) {
                // When a library is selected from the autocomplete list,
                // add that library to the "cdnjs_libraries" table by 
                // making an AJAX POST call to the "cdnjs_add_library" PHP action

                // Get the selected library object
                var library = ui.item.value;

                // Make an AJAX call to the "cdnjs_add_library" action
                $.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);
                        // Add the library to the table of managed libraries
                        $("#managed-libraries tbody").append(generateTableRow(library));
                    },
                    error: function(error) {
                        console.log(error);
                    }
                });
            }
        }).autocomplete( "instance" )._renderItem = function( ul, library ) {
            // Customize the display of the autocomplete options
            // Create a new list item for the library
            var listItem = $("<li>");
            // Create a link for the library
            var libraryLink = $("<a>", {
                href: library.url,
                target: "_blank",
                html: library.label
            });
            // Append the link to the list item
            listItem.append(libraryLink);
            // Return the list item
            return listItem.appendTo(ul);
        };


    });
    </script>
Share Improve this question edited Jan 9, 2023 at 4:20 Dustin asked Jan 8, 2023 at 7:34 DustinDustin 12 bronze badges 4
  • Your AJAX request is posting data as JSON. That’s not supported. No WordPress AJAX tutorials or documentation will show admin-ajax.php being used with JSON like this. – Jacob Peattie Commented Jan 8, 2023 at 7:47
  • All I'm trying to do I push a JS array into a custom Wordpress table (in a WP Admin-side plug-in). I've found a bunch of info on pushing JSON data to admin-ajax.php... it's just that it doesn't seem to work (maybe that should be obvious, based on your comment). So, should I be able to do what I'm wanting to do with my posted code... by setting the dataType & contentType parameters to a different value? I thought admin-ajax.php was just the mechanism to expose custom PHP actions, at which point I could send whatever type of data to be further processed/handled on the PHP/server side. – Dustin Commented Jan 8, 2023 at 18:27
  • Is this tutorial not using jquery.ajax to send json data via the admin-ajax.php file… with the action parameter being the name of a custom Wordpress function? wpmudev.com/blog/using-ajax-with-wordpress – Dustin Commented Jan 9, 2023 at 4:18
  • It is, but you’re not. Because you’ve used JSON.stringify you’re not sending an action parameter, you’re sending a JSON string with an action property in it. WordPress checks $_REQUEST['action'] to run the correct PHP but this is not populated by JSON. – Jacob Peattie Commented Jan 9, 2023 at 4:24
Add a comment  | 

1 Answer 1

Reset to default 0

To elaborate on my comments, your issue is here:

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

When sending data to admin-ajax.php you need to set the action property of data to the action name, eg. cdnjs_add_library. That's not what you're doing here. data is not an object with an action property, as is expected, it's a string containing JSON that happens to include an action property. These are not the same thing.

In the source of admin-ajax.php you'll see this:

$action = $_REQUEST['action'];

If you post JSON to admin-ajax.php $_REQUEST will not have an action property, for reasons I explain here. This means that your action will not be fired and your PHP code will not run.

The solution is to remove contentType and pass the data like so:

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

Your cdnjs_add_library_callback() function will then need to set $libary like this:

$library = $_POST['library'];
转载请注明原文地址:http://conceptsofalgorithm.com/Algorithm/1736266247a1105.html

最新回复(0)