最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

plugins - Create Proper WordPress Ajax Request in JavaScript, NOT jQuery

programmeradmin4浏览0评论

Okay, so I programmed the following ajax code for my plugin, and I'm wondering why it's not working:

JavaScript:

function myFunction() {

  let dataContent = "hello";

  let myData = {
    // Nonce
    _ajax_nonce: "<?php wp_create_nonce( 'nonce-name' );?>",
    // Action Hook name for Ajax Call
    action: 'my_action',
    // Currently typed username
    data: dataContent
  };
  // To send the JavaScript object to the server, convert it into a JSON string
  let myDataJSON = JSON.stringify(myData);
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      alert(this.responseText);
    }
  };
  let link = "<?php admin_url( 'admin-ajax.php' );?>";
  xhttp.open("POST", link, true);
  xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
  xhttp.send("data=" + myDataJSON);
}

PHP (Callback):

function answer() {
  check_ajax_referer( 'nonce-name' );
  echo "hello";
}

PHP (Hook):

add_action( 'wp_ajax_my_action', 'answer' );

When launching the call, I get "undefined" displayed in the alert window. What's wrong?

Okay, so I programmed the following ajax code for my plugin, and I'm wondering why it's not working:

JavaScript:

function myFunction() {

  let dataContent = "hello";

  let myData = {
    // Nonce
    _ajax_nonce: "<?php wp_create_nonce( 'nonce-name' );?>",
    // Action Hook name for Ajax Call
    action: 'my_action',
    // Currently typed username
    data: dataContent
  };
  // To send the JavaScript object to the server, convert it into a JSON string
  let myDataJSON = JSON.stringify(myData);
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      alert(this.responseText);
    }
  };
  let link = "<?php admin_url( 'admin-ajax.php' );?>";
  xhttp.open("POST", link, true);
  xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
  xhttp.send("data=" + myDataJSON);
}

PHP (Callback):

function answer() {
  check_ajax_referer( 'nonce-name' );
  echo "hello";
}

PHP (Hook):

add_action( 'wp_ajax_my_action', 'answer' );

When launching the call, I get "undefined" displayed in the alert window. What's wrong?

Share Improve this question edited Apr 14, 2020 at 19:28 fuxia 107k39 gold badges255 silver badges459 bronze badges asked Apr 14, 2020 at 16:57 JoeJoe 351 silver badge9 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 1

There are 4 filters to work with WordPress ajax. According to your description, the following conditions are assumed

  • wp_ajax_{$action} is for running in frontend and the user is logged in
  • if echo something in the php file, it will not reflect in the frontend. Javascript alert will output 'hello'
  • your javascript seems to be done in PHP and generate javascript, I suppose you have added proper header

According to WP Codex, the 4 filters for ajax are

  • wp_ajax_{$action} Fires authenticated Ajax actions for logged-in users.
  • wp_ajax_nopriv_{$action} Fires non-authenticated Ajax actions for logged-out users.
  • admin_post_{$action} Fires on an authenticated admin post request for the given action.
  • admin_post_nopriv_{$action} Fires on a non-authenticated admin post request for the given action.

Some facts about the code

  • There are missing echo to output nonce and admin_url
  • the script is actually not working (it is according to your shared code, there might be additional code. Anyway, if going to browser inspector, it gives 400 bad request error. It did not send ajax successfully.

There are a few issues in the code, here is the fixed script with missing pieces that I need for doing the test. I put the code into my theme functions.php and javascript code into test.php

In the testing, have put in the theme functions.php

// load the javascript
function q364077_enqueue_scripts()
{
    wp_enqueue_script('test-custom-scripts', get_theme_file_uri('/test.php'), array(), 't' . time(), true);
}
add_action('wp_enqueue_scripts', 'q364077_enqueue_scripts', 101);

// The ajax answer()
add_action( 'wp_ajax_my_action', 'answer' );
function answer() {
    // check_ajax_referer( 'nonce-name' );
    echo "hello";

    wp_die(); // terminate script after any required work, if not, the response text will output 'hello0' because the of function return after finish
}

The test.php is put in the theme folder, same level as functions.php

<?php
// inside the javascript test.php
/** Load WordPress Bootstrap */
// for test.php in theme folders
require_once( ( ( dirname( dirname( dirname( dirname( __FILE__ ) ) ) ) ) ) . '/wp-load.php' ); // to use admin_url(), if not, the script will be broken


// for output the javascript through php
header("Content-type: text/javascript");?>

function myFunction() {

    let dataContent = "hello";

    let myData = {
      _ajax_nonce: "<?php echo wp_create_nonce( 'nonce-name' );?>", // haven't added echo here, it is actually blank in output.
      // Action Hook name for Ajax Call
      action: 'my_action',
      // Currently typed username
      data: dataContent
    };
    // To send the JavaScript object to the server, convert it into a JSON string
    let myDataJSON = JSON.stringify(myData);

    var xhttp = new XMLHttpRequest();

    xhttp.onreadystatechange = function() {
      if (this.readyState == 4 && this.status == 200) {
        alert(this.responseText);
      }
    };

    let link = "<?php echo admin_url( 'admin-ajax.php' );?>"; // require "echo" to output, otherwise, it will alert unexpected output
    xhttp.open("POST", link, true);
    xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=UTF-8");

    // It is explained in the following, I use static value for illustration purpose
    xhttp.send('_ajax_nonce=efc5e4029d&action=my_action&data=hello');

The data need to be serialized, not only string. Your data look likes

{"_ajax_nonce":"efc5e4029d","action":"my_action","data":"hello"}

Ajax looks for this which jQuery has done for user. For Vanilla JS, it need to be done manually or using any existing vanilla js tools.

_ajax_nonce=efc5e4029d&action=my_action&data=hello

You may test the above code by fixing the 'echo' and putting a static value of the data to experience and may also go to the inspector, Chrome as an example.

in the inspector -> Network Tab -> when you fire myFunction() in console log, it return the status to you with request/response header, in that way, it helps bug fixing.

The above code tested and proved working in a fresh WordPress 5.3.2, default twenty twenty theme.

You're focusing on the script - side, but the addition of slashes to the json object only happens once the data is sent and received by the server, before being sent back to javascript. Guess I need to find out how to define the datatype in pure javascript in wordpress, with jquery its simply by using dataType:json (tried to serialize in pure js, didn't work, lmk if u get the answer, and thx!)

发布评论

评论列表(0)

  1. 暂无评论