Ajax

Overview

In WordPress, you can have three different Ajax access:

  • Only for logged-in users
  • Only for not-logged-in users
  • For everyone

Create an Ajax Service Provider

To create an Ajax Service Provider, you can use the following command:

php bones make:ajax MyAjax

By default, the new provider will be created in the plugins/Ajax directory. Of course, you may create your Service Provider manually and in any directory you prefer. You have to change the namespace accordingly.

/plugin/Ajax/MyAjax.php
<?php
class MyAjax extends WordPressAjaxServiceProvider
{
  /**
   * List of the ajax actions executed by both logged and not logged users.
   * Here you will use a methods list.
   *
   * @var array
   */
  protected $trusted = ["trusted"];
 
  /**
   * List of the ajax actions executed only by logged-in users.
   * Here you will use a methods list.
   *
   * @var array
   */
  protected $logged = ["logged"];
 
  /**
   * List of the ajax actions executed only by the not logged-in user, usually from the frontend.
   * Here you will use a methods list.
   *
   * @var array
   */
  protected $notLogged = ["notLogged"];
 
  /**
   * You may also define the capability required to execute the action.
   */
  protected $capability = "manage_options";
 
  /**
   * The nonce key used to verify the request.
   *
   * @var string
   */
  protected $nonceKey = "nonce";
 
  /**
   * The nonce hash used to verify the request.
   *
   * @var string
   */
  protected $nonceHash = "";
}

Edit the Ajax Service Provider

In the \WPKirk\Ajax\MyAjax class, you will list your methods/actions for logged-in, not logged-in, or trusted users:

The parent class WordPressAjaxServiceProvider will register on your behalf the WordPress actions that you need. So, let’s have a look at a complete example:

<?php
namespace WPKirk\Ajax;
 
use WPKirk\WPBones\Foundation\WordPressAjaxServiceProvider;
 
class MyAjax extends WordPressAjaxServiceProvider
{
  /**
   * List of the AJAX actions executed by both logged-in and not logged-in users.
   * Here you will use a methods list.
   *
   * @var array
   */
  protected $trusted = ["trusted"];
 
  /**
   * List of the AJAX actions executed only by logged-in users.
   * Here you will use a methods list.
   *
   * @var array
   */
  protected $logged = ["logged"];
 
  /**
   * List of the AJAX actions executed only by the not logged-in users, usually from the frontend.
   * Here you will use a methods list.
   *
   * @var array
   */
  protected $notLogged = ["notLogged"];
 
  /**
   * The capability required to execute the action.
   * Of course, this is only for logged-in users.
   *
   * @var string
   */
  protected $capability = "";
 
  /**
   * The nonce key used to verify the request.
   *
   * @var string
   */
  protected $nonceKey = "nonce";
 
  /**
   * The nonce hash used to verify the request.
   *
   * @var string
   */
  protected $nonceHash = "";
 
  public function trusted()
  {
    $response = "You have clicked Ajax Trusted";
 
    wp_send_json($response);
  }
 
  public function logged()
  {
    $response = "You have clicked Ajax Logged";
 
    wp_send_json($response);
  }
 
  public function notLogged()
  {
    $response = "You have clicked Ajax notLogged";
 
    wp_send_json($response);
  }
}

You can also get the post variables by using $this->request->get('post_name'). WordPress provides several functions to return a JSON result. For example, you may use:

wp_send_json_succcess();

or

wp_send_json_success(["hello" => "world"]);

In JavaScript side, you’ll find:

$.post(ajaxurl, {}, function (response) {
  if (response.success) {
    // success property is set by WordPress wp_send_json_success
  } else {
    // also data property is set by WordPress wp_send_json_success
    // but it contains your custom array/object
    alert(response.data.hello);
  }
});

The wp_send_json_error function works in the same way.

Security

You may protect your Ajax calls by using two main methods: by the simple capability property or by the nonce key.

Capability

You can set the capability property in the class to protect the Ajax call. For example, if you want to allow only the manage_options capability, you can set the $capability property to manage_options.

Nonce

You can set the nonce key and hash properties in the class to protect the Ajax call. To enable the nonce protection, you have to set the $nonceHash property with a key used to generate the nonce.

/**
 * The nonce key used to verify the request.
 *
 * @var string
 */
protected $nonceKey = "nonce";
 
/**
 * The nonce hash used to verify the request.
 *
 * @var string
 */
protected $nonceHash = "anything-you-want";

The $nonceKey property is the name of the post variable that will be sent to the server. The $nonceHash property is the string used to generate the nonce.

Next, you have to generate the nonce in your Controller and make it available to the JavaScript side. You can use the withLocalizeScript method to pass the nonce to the JavaScript side.

If you are using a ReactJS application, you may use something like this:

class DashboardController extends Controller
{
  public function index()
  {
    return WPKirk()
      ->view("dashboard.index")
      ->withLocalizeScript("app", "WPKirkNonce", [
        "nonce" => wp_create_nonce("anything-you-want"),
      ])
      ->withAdminAppsScript("app", true);
  }
}

The code above will create a global variable WPKirkNonce with the nonce value. You can use it in your ReactJS application like this:

/**
 * Post data to the server.
 *
 * @param {string} action The action to be executed. Eg. "logged"
 * @returns {Promise<any>}
 */
const post = async action => {
  const res = await fetch(window.ajaxurl, {
    method: "POST",
    body: new URLSearchParams({
      action,
      nonce: WPKirkNonce.nonce,
    }),
    headers: {
      // form-data url encoded
      "Content-Type": "application/x-www-form-urlencoded",
    },
  });
  return res.json();
};
post("logged").then(response => {
  console.log(response);
});
đź’ˇ

You may use the same also in Vanilla JavaScript or any other JavaScript framework. Most probably, in WordPress you are used to jQuery, so you can use the $.post method.

$.post(
  ajaxurl,
  {
    action: "logged",
    nonce: WPKirkNonce.nonce,
  },
  function (data) {
    alert(data);
  }
);

Load the Ajax Service Provider

To allow Ajax calls, you need to edit the /config/plugin.php file. In the Ajax section, you can insert the list of your own Ajax classes, for example:

/config/plugin.php
  /*
  |--------------------------------------------------------------------------
  | Ajax
  |--------------------------------------------------------------------------
  |
  | Here is where you can register your own Ajax actions.
  |
  */
 
  'ajax' => [ '\WPKirk\Ajax\MyAjax' ],