0

after digging through a lot of Ajax Bad Request 400 problems here on SO, that, unfortunately, didn't help me to solve this problem.

After instantiating my custom post, I add a submenu page where I instantiate my admin functionality, which in turn execute some ajax.

custom post:

class customDomain{

private $wpPluginAdmin;

public function __construct(){
  ...
  add_action('admin_menu', array($this, 'add_sub_menu_pages'));
  ...
}

public function add_sub_menu_pages()
{
  add_submenu_page(
    ...
  );
  $this->wpPluginAdmin = new PluginAdmin();
}

}//endclass
$custom_domain = new CustomDomain();

PluginAdmin:

  
 //...
public function __construct()
{
  $this->pluginPath = dirname(__FILE__);
  $this->db_handler = DatabaseHandler::get_instance();

  add_action('admin_print_styles', array($this, 'add_admin_styles'));
  add_action('admin_enqueue_scripts', array($this, 'add_admin_scripts'));
  add_action('wp_ajax_add_vehicle', array($this, 'add_vehicle'));
  add_action('wp_ajax_nopriv_add_vehicle', array($this, 'add_vehicle'));
}

public function add_admin_scripts()
{
  wp_enqueue_script('admin_scripts', plugins_url('js/functions.admin.js', __FILE__), array('jquery'));
  wp_localize_script(
    'admin_scripts',
    'ajax_object',
    array(
      'ajaxurl' => admin_url('admin-ajax.php'),
      'nonce' => wp_create_nonce('ajax-nonce')
    )
  );
}

public function add_vehicle()
{
  // var_dump($_POST);
  // die();

  $nonce = $_POST['nonce'];

  if (!wp_verify_nonce($nonce, 'ajax-nonce')) {
    die('Busted!');
  }

  //add new vehicle to database
  $this->db_handler->admin_insert_vehicle($_POST['vehicle']);
  $id = $this->db_handler->get_last_insert_id();
  $vehicle = (object) array(
    'id' => $id,
    'description' => $_POST['vehicle']
  );

  $response = json_encode($vehicle);

  // response output -> sent back to javascript file
  // header("Content-Type: application/json");
  wp_send_json($response);
}

My JS function:

var $ = jQuery;
var addVehicle = function () {

    $('.add-vehicle').click(function () {
        var data = {
            action: 'add_vehicle',
            nonce: ajax_object.nonce,
            vehicle: {
                'description': $('#vehicle_description').val(),
                'radio_id': $('#vehicle_radio_id').val(),
                'location': $('#vehicle_location').val(),
            }
        };

        $.ajax({
            type: 'POST',
            url: ajaxurl,
            data: data,
            success: function (data, textStatus, XMLHttpRequest) {
                $('#message').show();

                $('.tab-vehicle').append('<tr>' +
                    '<td>' + data.id + '</td>' +
                    '<td>' + data.description + '</td>' +
                    '<td>' + data.radio_id + '</td>' +
                    '<td>' + data.location + '</td>' +
                    '<td><i class="fas fa-edit"></i></td>' +
                    '<td><i class="fas fa-trash-alt"></i></td>' +
                    '</tr>');
                $('#message').fadeOut(2000);
            },
            error: function (MLHttpRequest, textStatus, errorThrown) {
                console.log(errorThrown);
            }
        });
    });
};
jQuery(document).ready(function ($) {
    addVehicle();
});

When I'm debugging into the JS function and go step by step, I manage to get into the error callback, when just executing it, it looks like nothing happens. The add_vehicle function isn't called.

Sending out a postman request to http://localhost:8000/wp-admin/admin-ajax.php?action=add_vehicle return 0 with an HTTP 400. At least I expected the same result when my JS coding is executed, but neither in the console nor anywhere else is the HTTP 400 is displayed.

thanks, mybecks

EDIT:

I have refactored the class AdminPlugin that it got instantiated after the plugin gets activated (so I removed it from the custom post add menu action), now I got a positive response (also with postman). But nothing of my "debugging" try is working and it looks like nothing of the code is executed.

PluginAdmin:

class PluginAdmin {  
 //...
public function __construct()
{
  $this->pluginPath = dirname(__FILE__);
  $this->db_handler = DatabaseHandler::get_instance();

  add_action('admin_print_styles', array($this, 'add_admin_styles'));
  add_action('admin_enqueue_scripts', array($this, 'add_admin_scripts'));
  add_action('wp_ajax_add_vehicle', array($this, 'add_vehicle'));
  add_action('wp_ajax_nopriv_add_vehicle', array($this, 'add_vehicle'));
}

public function add_admin_scripts()
{
  wp_enqueue_script('admin_scripts', plugins_url('js/functions.admin.js', __FILE__), array('jquery'));
  wp_localize_script(
    'admin_scripts',
    'ajax_object',
    array(
      'ajaxurl' => admin_url('admin-ajax.php'),
      'nonce' => wp_create_nonce('ajax-nonce')
    )
  );
}

public function add_vehicle()
{
  // var_dump($_POST);
  // die();

  $nonce = $_POST['nonce'];

  if (!wp_verify_nonce($nonce, 'ajax-nonce')) {
    die('Busted!');
  }

  //add new vehicle to database
  $this->db_handler->admin_insert_vehicle($_POST['vehicle']);
  $id = $this->db_handler->get_last_insert_id();
  $vehicle = (object) array(
    'id' => $id,
    'description' => $_POST['vehicle']
  );

  $response = json_encode($vehicle);

  // response output -> sent back to javascript file
  // header("Content-Type: application/json");
  wp_send_json($response);
}
}//end class
$wpPluginAdmin = new PluginAdmin();

EDIT 2:

I did, based on the suggestion in the comments, a complete refactoring and are using the WP REST API from now on.

4
  • Why are you creating your PluginAdmin object on the admin_menu hook? This means your AJAX endpoints don't exist on pages that don't have an admin menu ( frontend/RSS/AJAX/REST/etc ) and neither does any of the other hooks that get added, they never have the chance to run. You also have typos and syntax errors near $vehicle = (object) array( that your PHP error log should have told you about – Tom J Nowell Feb 9 at 11:57
  • Thanks for pointing it out. The typo was some transfer issue. I removed the initialization of the AdminPlugin to the file itself and now I'm getting at least a empty success response, but no var_dump in any of the action handler is working. It looks like as there is nothing executed. I update the code examples in the original post. – mybecks Feb 9 at 12:27
  • Also how are you testing for those var dumps? And is there a reason you used the old legacy Admin AJAX api instead of making an AJAX request to a REST API endpoint? It's worth looking into, if only because you don't need to handle the nonce on the server end ( the REST API does it and a tonne of other stuff for you ) – Tom J Nowell Feb 9 at 12:43
  • Thanks for the hint. I did a complete refactoring using the WP REST API. Now it works :) – mybecks Feb 11 at 9:08
0

I noticed something in your ajax call.

$.ajax({
            type: 'POST',
            url: ajaxurl,
            data: data,

Shouldn't it be ajax_object.ajaxurl instead of just ajaxurl ?

3
  • The official docs points out: NOTE: Since Version 2.8, The JavaScript global variable ajaxurl can be used in case you want to separate your JavaScript code from php files into JavaScript only files. This is true on the administration side only. If you are using AJAX on the front-end, you need to make your JavaScript aware of the admin-ajax.php url. A best practice is documented in the fourth example, below using wp_localize_script(). – mybecks Feb 9 at 12:24
  • @mybecks That doesn't contradict what Sabbir is saying. On the front end there is no global variable, you need to use ajax_object.ajaxurl. – Jacob Peattie Feb 9 at 13:09
  • @JacobPeattie thanks, I changed it. – mybecks Feb 9 at 17:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.