If you’re getting ready to read this post, there’s a good chance you’ve at least heard of AJAX. You might even know what it is and what it does. For those of you who don’t know what it is or does, here’s a quick overview:
AJAX (short for “asynchronous JavaScript and XML”) is a group of interrelated Web development techniques used on the client-side to create asynchronous Web applications. With AJAX, web applications can send data to and retrieve from a server asynchronously (in the background) without interfering with the display and behavior of the existing page.
Unlike many web-related technology definitions, this one is relatively easy to digest, at least in my opinion. What it’s saying is that AJAX isn’t a programming language, per se, but rather a set of techniques. It’s used to pass data back and forth between your browser (client) and server without having to refresh the page.
“When would I want to use AJAX?”, you may ask. AJAX can be used for a lot of awesome things. For example, you can submit forms, load posts, log users in/out, and a lot more, all without having to refresh the page.
Getting Started with AJAX and WordPress
First, I highly recommend you watch this video from Pippin Williamson. It is the best instructional material I’ve found for using AJAX. In the video, Pippin shows you how to use AJAX in the WordPress admin. For the rest of this post, I’ll show you how to do something with AJAX in both the front-end and admin.
Before diving in, I’ve created a simple “conversation” between WP (server) and JS (client) that will, hopefully, provide some context by highlighting the basic client-server communication that goes on when processing the AJAX requests in this tutorial:
WP: Hey, JS. We need to get together and perform logouts for users and dismissing an admin notice without requiring page reloads. I’m going to give you some files that you’ll be working with. I’m also going to send you some variables containing data you’ll need.
JS: Got it. What am I doing with everything?
WP: I need you to listen for when a special link is clicked by the user. When it is, you’ll let me know by sending a background (asynchronous) request to my dedicated AJAX processor/file. I’m going to process the request, and either terminate the user’s login session, or add some information about the user that will prevent them from seeing the admin notice in the future. I’ll let you know when I’m done, and I’ll give you a response that you can use to display a message to the user as feedback.
JS: Let’s do this!
Lastly, to process AJAX requests on your WordPress website, you’ll need to be able to prepare some JavaScript (jQuery) and PHP. For this tutorial, we’re going to create a plugin that processes a couple requests: 1.) an admin request to dismiss an admin notice, and 2.) a front-end request to log the current user out of his or her account. These will be very basic examples, but they will show you the process of sending and processing AJAX requests in both the admin and front-end. If you’d like to look at the plugin before going any further, you can view and download the source on GitHub.
Plugin Setup
I want to quickly give you a rundown of how the plugin is set up before getting into the specifics of using AJAX in WordPress. First off, looking at the main plugin file, wp-ajax-tut.php, you may notice that the plugin is written using an Object Oriented model (OOP = Object Oriented Programming). If this freaks you out, don’t let it. It can be tricky to get the hang of because it’s a different concept from that of procedural programming, which is what most new programmers are used to. I’ll also be sure to explain some of these OOP nuances.
Next, you’ll see the instance()
method. I use this for all of my plugins that I develop because it checks to see if the class has already been instantiated, and, if it has, returns that instance rather than a new instance. Otherwise, it sets everything up for a new instance. This is a cleaner way of doing things. This method also runs the constants()
and hooks()
methods.
If the words “method”, “instantiated”, and “instance” are confusing, let me try to clear it up. If you are familiar with a function, then you know what a method is, because a method is a function within a class. It’s just called a method because it is used in a class. What is a class? It’s a modular piece of code that is written to perform a task. Typically, you’ll have multiple classes in a plugin, and each class will do something different. In this tutorial, the amount of code is small enough to use just one class. So, then, what do “instantiation” and “instance” mean? Instantiation is simply declaring a new instance of a class. Think of a class as the blueprints for a model/spec home. The class says how this home is built and what it does. There is only one of that class. An instance, however, would be a specific house that was built using that blueprint. There can be many instances of the houses that were built using the same blueprint. This is how classes and instances work.
The constants()
method simply defines constants used in the plugin. The hooks()
method kicks everything off by telling WordPress when our code will be hooking into the loading process. If you are new to programming, you’re likely used to seeing something like this:
<?php /** * Procedural way of doing things */ add_action( 'action_hook', 'action_callback_function' ); function action_callback_function() { // Do something here } add_filter( 'filter_hook', 'filter_callback_function' ); function filter_callback_function( $arg ) { // Do something with $arg return $arg; }
In this object-oriented plugin, I’ve created the hooks() method, which is where the add_action()
and add_filter()
functions go. You’ll also see that this type of syntax is used when passing the callback parameter:
add_action( 'wp_head', array( $this, 'logout_button' ) );
This is different from the code above because our callback function/method is within the scope of a class. Passing only the name of the function will not work because that function is not within a global scope. Therefore, we need to also pass in the name of the class that the method is within. This is done by passing an array as the second parameter, with the name of the class as the first element, and the name of the method as the second. When you see $this
, it means that the code is referring to its own class and not a separate class.
Now that I’ve laid out some OOP basics for beginners, let’s look at the real purpose of the plugin: AJAX.
Admin AJAX Request – Dismiss Admin Notice
In this first request, we’re going to look at setting up a basic admin notice and dismissing that notice via AJAX. You’re likely familiar with WordPress admin notices in the forms of update nags, settings-updated notices, and error notices. They’re simple content boxes shown at the top of an admin page, and they have either a green (success), red (error) or orange (update nag) border on the left side. Our admin notice will show a basic message and a close icon that indicates to the user that he or she can dismiss the notice.
PHP
The hook we’re using is the admin_notices action.
add_action( 'admin_notices', array( $this, 'admin_notice' ) );
Our callback method outputs the markup for the notice, which will be an “update-nag” (has a yellow/orange border on the left).
/** * Add our admin notice if the user has not previously dismissed it. */ public function admin_notice() { ?> <?php // Bail if the user has previously dismissed the notice (doesn't show the notice) if ( get_user_meta( get_current_user_id(), 'wp_ajax_tut_admin_notice', true ) === 'dismissed' ) { return; } ?> <div id="wp-ajax-tut-notice" class="notice is-dismissible update-nag"> <?php _e( 'This is the admin notice for the WP-AJAX Tutorial plugin. It does nothing more than add this message. You should not see it anymore after clicking the dismiss icon.', 'wp-ajax-tut' ); ?> </div> <?php }
In this method, we’re first checking to see if the current user has already dismissed the notice. We do this by using get_user_meta()
to see if any meta has been saved and if it equals “dismissed.” If it does, we bail out of the code because the user has dismissed. I’ll be explaining shortly how this user meta gets saved. If no such user meta exists, we proceed to output the markup for the notice. By adding the classes “notice” and “update-nag,” WordPress takes care of the styling for us. By adding the class “is-dismissible,” WordPress also adds the little dismiss icon that makes the notice disappear (it does not “permanently” dismiss it, though). The above code gives us an admin notice that looks like this:
Before getting to the JavaScript, I’m going to jump ahead a little to show you the rest of the PHP, which involves processing the AJAX request.
/** * Enqueue the assets in the admin */ public function enqueues() { // Add the admin JS if the notice has not been dismissed if ( is_admin() && get_user_meta( get_current_user_id(), 'wp_ajax_tut_admin_notice', true ) !== 'dismissed' ) { // Adds our JS file to the queue that WordPress will load wp_enqueue_script( 'wp_ajax_tut_admin_script', WP_AJAX_TUT_PLUGIN_URL . 'assets/js/wp-ajax-tut-admin.js', array( 'jquery' ), WP_AJAX_TUT_VERSION, true ); // Make some data available to our JS file wp_localize_script( 'wp_ajax_tut_admin_script', 'wp_ajax_tut_admin', array( 'wp_ajax_tut_admin_nonce' => wp_create_nonce( 'wp_ajax_tut_admin_nonce' ), )); } } /** * Process the AJAX request on the server and send a response back to the JS. * If nonce is valid, update the current user's meta to prevent notice from displaying. */ public function dismiss_admin_notice() { // Verify the security nonce and die if it fails if ( ! isset( $_POST['wp_ajax_tut_admin_nonce'] ) || ! wp_verify_nonce( $_POST['wp_ajax_tut_admin_nonce'], 'wp_ajax_tut_admin_nonce' ) ) { wp_die( __( 'Your request failed permission check.', 'wp-ajax-tut' ) ); } // Store the user's dimissal so that the notice doesn't show again update_user_meta( get_current_user_id(), 'wp_ajax_tut_admin_notice', 'dismissed' ); // Send success message wp_send_json( array( 'status' => 'success', 'message' => __( 'Your request was processed. See ya!', 'wp-ajax-tut' ) ) ); }
What you’re seeing here is a condensed version of the enqueues() method and the full dismiss_admin_notice() method. I included code from the enqueues() method here because, as you see, we first check to verify a security nonce before proceeding. This nonce is created and made available to our JS file by way of wp_localize_script(). This function is one of the most helpful functions in all of WordPress because it allows developers to easily pass any data to be used in JavaScript. The first parameter in this function is the handle of the script we’re enqueuing, the object name we’re giving to the data, and an array of data. In this admin notice example, we’re creating an array with only one element: the nonce. Note that the parameter for wp_create_nonce()
is basically the ID of the nonce.
Next, we have to hook into the WordPress-AJAX process.
add_action( 'wp_ajax_wp_ajax_tut_admin_notice', array( $this, 'dismiss_admin_notice' ) );
The first parameter here needs some explanation. First, the part that comes after “wp_ajax_” is what’s critical here because this is a dynamically named hook. This part is commonly called the “action.” I’ll show you where this comes from when we get to the JavaScript. Next, the admin-ajax.php file in WordPress allows for running action hooks based on a user’s login status. There are two hooks for this: “wp_ajax_” (for logged in users) and “wp_ajax_nopriv_” (for logged out users; meaning no privileges). For our purposes, we don’t need to run the request for logged out users because the only users who can see the notice will be logged in. Therefore, we only use the “wp_ajax_” hook.
When the AJAX script sends the request to the server, we’ll be having it do so via the HTTP POST method. Therefore, we want to retrieve the data from the request using the $_POST variable. This is how we access the nonce, which is then verified by running the $_POST value through wp_verify_nonce()
. This function takes a nonce value and the “ID” of the nonce, respectively. If the nonce is set and verified, we move on.
Finally, assuming the security check passed, we update the user’s meta with a new entry. The key is “wp_ajax_tut_admin_notice” and the value is “dismissed”, which you saw earlier. After that, we send a JSON response, which is a JavaScript object with two parts: a status and a message. This part is not necessary, but I wanted to use it to show you how wp_send_json()
works. Since we only need to update the user’s meta and not send a response, we don’t need it. However, when you want to send something back to the user, such as a success message, you’d use this function. It’s actually a very useful function because it eliminates the need for you having to json_encode() an array, echo it out, and die(). The wp_send_json() function does all that for you.
JavaScript
The first thing we need to do is add the JS that tells the browser what to do. To do this, we have to create the JS file and enqueue it via PHP. The enqueue process was handled in the enqueues() method.
wp_enqueue_script( 'wp_ajax_tut_admin_script', WP_AJAX_TUT_PLUGIN_URL . 'assets/js/wp-ajax-tut-admin.js', array( 'jquery' ), WP_AJAX_TUT_VERSION, true );
We also checked to make sure this file is enqueued only when the user is in the admin and has not previously dismissed the notice.
jQuery(document).ready(function($) { /** * Process request to dismiss our admin notice */ $('#wp-ajax-tut-notice .notice-dismiss').click(function() { //* Data to make available via the $_POST variable data = { action: 'wp_ajax_tut_admin_notice', wp_ajax_tut_admin_nonce: wp_ajax_tut_admin.wp_ajax_tut_admin_nonce }; //* Process the AJAX POST request $.post( ajaxurl, data ); return false; }); });
This bit of jQuery is doing a few things. First, it’s listening for when the notice icon (.notice-dismiss) within the notice container (#wp-ajax-tut-notice) is clicked. When that happens, it creates an object of data. This object includes the action, which is used to dynamically create the hook name for hooking into the AJAX process. This value has to go after the “wp_ajax_” in the hook name, hence our hook name of “wp_ajax_wp_ajax_tut_admin_notice.”
The data object also includes the nonce value that was made available to our script via wp_localize_script()
. The nonce value is accessed by “wp_ajax_tut_admin.wp_ajax_tut_admin_nonce,” which is the name of the object we gave our data in wp_localize_script() and the nonce element’s key.
Lastly, the script sends the POST request via the $.post() function. Without getting into too much detail about this function, it accepts four parameters, and we’re only going to be interested in the first three. The first parameter is the URL to which we’re sending the request. WordPress provides a default variable for the URL to admin-ajax.php, which is only available when in the admin. This variable is ajaxurl
, which is what we’re passing into the function. The second parameter is the data object we’re sending to the server. You’ll see the third parameter in the next section.
Revisiting the PHP
Now, let’s head back to the PHP for dismissing the admin notice, as we will be able to pull things together after seeing the JavaScript.
Remember the process of retrieving POST data? We used the $_POST variable. The data contained in this variable was just sent via the AJAX request. We pluck out values by calling the $_POST variable and passing it a key. The keys we can use are the keys used in the data object in the JS. You won’t really ever use the action key, so we’ll only be using the “wp_ajax_tut_admin_nonce” key. Therefore, when retrieving the nonce value, we used $_POST['wp_ajax_tut_admin_nonce']
. This is how we’ll retrieve all data elements.
Front-end AJAX Request – End User’s Login Session
You made it through the admin part of the tutorial. Now, onto the frontend half. You should now be able to see where things are going, but there will be some differences.
PHP
First, let’s cover a couple of the hooks we need for this section.
add_action( 'wp_enqueue_scripts', array( $this, 'enqueues' ) ); add_action( 'wp_head', array( $this, 'logout_button' ) );
First, we’re using both the admin_enqueue_scripts and wp_enqueue_scripts hooks in this tutorial. The reason for that is because WordPress loads scripts in the frontend using wp_enqueue_scripts, and it loads scripts in the admin using admin_enqueue_scripts. I decided to use one method with extra conditionals, rather than two different methods. If you so desire, you could split this into two different methods.
// Add the front-end JS for the logout link if ( ! is_admin() && is_user_logged_in() ) { wp_enqueue_script( 'wp_ajax_tut_frontend_script', WP_AJAX_TUT_PLUGIN_URL . 'assets/js/wp-ajax-tut-frontend.js', array( 'jquery' ), WP_AJAX_TUT_VERSION, true ); /** * The big difference here is the ajax_url element; we need to make it * available on the frontend because WordPress does not do this itself */ wp_localize_script( 'wp_ajax_tut_frontend_script', 'wp_ajax_tut_frontend', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ), 'wp_ajax_tut_frontend_nonce' => wp_create_nonce( 'wp_ajax_tut_frontend_nonce' ), )); }
Again, we are creating a security nonce and passing it to our script via wp_loalize_script()
. However, this time, we’re also passing the full URL of admin-ajax.php to the script. This step is required because WordPress does not provide the ajaxurl variable in the frontend like it does in the admin. Note also the handle of the frontend script and the name of the data object (array in the third parameter).
Next, we’re hooking into wp_head to output the logout button.
/** * Add the markup for the logout button */ public function logout_button() { if ( is_user_logged_in() ) { printf( '<button id="wp-ajax-tut-logout" style="position: fixed; top: 50px; left: 0; z-index: 999;">%s</button>', __( 'Logout', 'wp-ajax-tut' ) ); } }
This checks to see if the user is logged in, and, if yes, outputs a button with some inline styling (fixed position and 50px from the top) to keep it visible at all times. Note the ID of wp-ajax-tut-logout for the button.
JavaScript
This time, let’s move to the JS before wrapping up.
jQuery(document).ready(function($) { /** * Process request to end the user's login session */ $('#wp-ajax-tut-logout').click( function() { var $this = $(this), button_text = $this.text(), ajaxurl = wp_ajax_tut_frontend.ajaxurl; //* Data to make available via the $_POST variable data = { action: 'wp_ajax_tut_logout', wp_ajax_tut_frontend_nonce: wp_ajax_tut_frontend.wp_ajax_tut_frontend_nonce }; // Disable the button and provide some feedback to the user $this.prop('disabled','disabled').text('Logging out...'); //* Process the AJAX POST request $.post( ajaxurl, data, function(response) { if ( response.status == 'success' ) { // Show success message, then fade out the button after 2 seconds $this.text(response.message).delay(2000).fadeOut(); } else { // Re-enable the button and revert to original text $this.removeProp('disabled').text('Logout failed.').delay(2000).text(button_text); } }); return false; }); });
As this script is more involved than the previous, I’ll list out the steps being taken here:
- Listening for clicks on the logout button (#wp-ajax-tut-logout).
- Create three variables: one for the actual logout button element, one for the button’s original text, and one for the admin-ajax.php URL we sent via wp_localize_script(). This is done for caching and ease of reading.
- Create the data object that will be sent to the server. This data includes the action name (remember “wp_ajax_”) and nonce value that was also sent via wp_localize_script().
- Disable the button to avoid multiple, simultaneous requests from the same user, and change the text to “Logging out…” so to provide the user with some feedback that he or she successfully clicked it.
- Send the data via the POST method to the admin-ajax.php URL.
- After the request, check the JSON response. If the “status” key is equal to “success,” then show the value of the “message” key, which is “Logged out. See ya!” and fade out the button after two seconds. If anything else, change the button’s text to “Logout failed” and revert the text to the original “Logout” after two seconds.
Back to the PHP
Now to process the logout request.
/** * End the user's login session */ public function logout() { // Verify the security nonce and die if it fails if ( ! isset( $_POST['wp_ajax_tut_frontend_nonce'] ) || ! wp_verify_nonce( $_POST['wp_ajax_tut_frontend_nonce'], 'wp_ajax_tut_frontend_nonce' ) ) { wp_die( __( 'Your request failed permission check.', 'wp-ajax-tut' ) ); } // Destroy user's session wp_logout(); // Send success message wp_send_json( array( 'status' => 'success', 'message' => __( 'Logged out. See ya!', 'wp-ajax-tut' ) ) ); }
Again, we check to verify the security nonce, and proceed only if it verifies. Assuming it does, run the wp_logout()
function, which simply destroy’s the user’s session. Lastly, we send a JSON object back to the user via wp_send_json()
. The success key/value is used to determine what to do with the button, and the message key/value is used to display a successful logout message to the user.
Wrapping Up
There you have it! These two simple WordPress-AJAX requests to dismiss an admin notice and terminate a user’s login session are trivial examples, but they are great to implement on your own to get your feet wet with AJAX. Once you implement a few AJAX features, the process will become second nature to you. The important thing to remember is that there are a lot moving parts when working with AJAX, and your code needs to be written carefully because even slight differences can cause the whole process to fail.
Again, here’s the link for the tutorial’s plugin. Look through it, study, and use it in your own code.
I hope you enjoyed the post, and feel free to leave your questions in the comments.
Leave a Reply