Ajax can be a confusing topic. I’ve spoken with developers who didn’t have a grasp of where Javascript ended and Ajax began. So before we dip into Ajax with WordPress, lets take a look at ajax itself.
Ajax is a request to your server
At it’s heart, Ajax is nothing more than an http request. It is a single request to a server which then sends back a response. This is very similar to typing in an address in your browser and hitting enter. It makes a request to a server which then sends back a response.
The magic of Ajax is that this is done without unloading the current page and loading a new one.
Javascript is what controls these requests. It originates the request, and when the response comes back, Javascript receives it and can process it. Ajax does’t submit forms. Ajax doesn’t update content. Ajax doesn’t do anything with your page at all. It’s only a request. Javascript does all that. Ajax simply provides a means of giving Javascript the data it needs to update and manipulate your page correctly.
Ajax pitfalls
When reaching for Ajax as a tool to get data for Javascript, you should consider some possible pitfalls that are common.
The ability to do Ajax correctly in a cross browser manner has been traditionally very difficult. The Javascript objects that enabled it were named different things and behaved slightly differently. While time has helped, and there is far more standards compliance across browsers, there are still potential problems here if you are trying to roll plain Javascript Ajax requests.
It doesn’t refresh your page, either. This is what makes Ajax fun to work with, because you can change parts of your page without needing to reload it entirely. The problem is history goes out the window. Ajax requests don’t cause history to be added to the browser, so if you make large changes and the user then refreshes page, or they hit the back button expecting to step back one change, it just doesn’t work.
Once again, with newer browser apis, you can actually push history to the browser without a refresh or hacking hashes, but this is something you have to consider before you build your system. Tacking it on at the end will be difficult, and likely end up being a poor experience for your visitors.
These are both problems that have been solved a myriad of ways over the years. I’m not going to go into how to solve them exactly here, but I do think it’s important for someone starting with Ajax to be aware of issues they might face before getting started.
Ajax in WordPress
If you develop in WordPress, a lot of work has been done to make using Ajax more simple. The heart of this is the wp-admin/admin-ajax.php
file. The entire purpose of this file is handling Ajax requests.
admin-ajax.php
When the admin Ajax file receives a request, it takes care of firing up the WordPress engine for you and getting everything initialized. It then inspects the request for an action. This is nothing more than an arbitrary string value. If no action is sent in the request, it will die with 0
, indicating failure. For example purposes, let’s pretend the action sent in a request is ‘get_comments’.
Once WordPress has initialized, it fires one of two actions depending on login status. If the user is logged in, WordPress will fire wp_ajax_get_comments
. You can hook into this action and further process the request and send a response. If the user is not logged in (i.e. has no privileges) WordPress will fire wp_ajax_nopriv_get_comments
.
This is a nice way to split behaviors. If an action using Ajax should only be performed in the admin section, don’t use the _nopriv_
hook. It helps keeps everything just a little more secure.
Notice also that the end of the fired action, the ‘get_comments’ part in our example, really can be any string. Take a look at the end of the actual file. You’ll see where this is happening.
The important thing to remember when sending a request is to make sure you are sending an action, either as a $_GET
parameter, or as a $_POST
parameter.
Processing the request
So now we’ve fired an action. If nothing happens in that action, WordPress will still die with ‘0’. So to make sure that doesn’t happen, we need to add an action callback to process the request and send a response.
This part was a bit confusing for me at first. I understood the action callback bit, but I was expecting something more complicated for sending back a response. Anything you output will be sent back as the response. You can echo out a string. You can drop out of PHP and write HTML or XML. You can output JSON. It is no different than when you output HTML when writing normal templates, but in this case it is sent back to Javascript rather than to the browser.
Once you output your response, use die()
or exit()
so that WordPress stops processing the request and extra unintended output doesn’t get sent back as well.
Nonces
When performing any Ajax requests, they should also send along a nonce and check it before doing any processing. The admin ajax processor doesn’t check nonces, so this is something you need to handle manually to make sure your request remains secure. Without nonces, anyone can fire a request for the data to the endpoint with a _nopriv_
callback. They don’t need to be on your site, they just need to make the request.
Even a privileged action callback is not completely safe. All it checks is whether or not the user has a login cookie. It doesn’t matter what kind, or what capabilities they have, as long as they have something that makes it look like they are logged in then the action will fire and process the request.
Nonces help ensure the requests are valid by using a hidden bit of data that it combined with a time sensitive component to authenticate the request’s origin. Check out the codex for some more data on nonces and how to implement them in WordPress in different contexts.
Generating Ajax Requests
Ajax requests come from and end in Javascript. They are a way of getting additional data, then Javascript takes over and processes the request and updates the page accordingly. Generating them with Javascript alone can be a tricky business, but not impossible. However, for our purposes, we’ll take a quick look at using the jQuery library to generate them. Using jQuery abstracts away cross browser issues quite well. This doesn’t always mean it’s always the right answer, but for many situations it is already present, especially when working with WordPress.
The main method jQuery offers is jQuery.ajax()
. There are also a myriad of other helper methods for different types of requests, but they typically all come back to jQuery.ajax
to run the actual data request.
There are many different ways to configure and customize the Ajax object, but most of the time they are not needed. The majority of the time all that is needed is the url send the request to, the data to be sent with the request in an object, and the callback functions to handle the successful or erroneous responses that may come back.
A typical request may look like this:
var nonce = wpNonce; // Note this is something passed from PHP.
function handleSuccess( data ) {
//use data to update DOM as needed
}
function handleError( data ) {
//handle the error and report the failure to the user in some way
}
jQuery.ajax(
"http://lkwdwrd.com/wp-admin/admin-ajax.php",
{
type: "POST",
data: {
action: "get_comments",
nonce: nonce
},
error: handleError,
success: handleSuccess
}
);
We send the request to the admin-ajax endpoint as a POST request, which populates our data into the $_POST
super global. We sent the ‘get_comments’ action which means either wp_ajax_get_comments
or wp_ajax_nopriv_get_comments
action will fire to process the request. Remember, in the callback we will need to verify the nonce before we further process the request.
It is important to note that the handleError
callback here will fire if the request itself fails. To indicate if processing failed or not you need to have an identifier of some kind in your response. Even if you send no action and WordPress sends back “0”, it is still considered a “successful” request. The request is fine, it was response that wasn’t what we expected.
If the request is successful, the handleSuccess
callback is called to process the data sent back. This is where the returned data can be used to decided where and how to update the DOM with Javascript.
PHP JSON Response Helpers
Since WordPress 3.5, when processing the request the callback in PHP, there are two very useful helpers. wp_send_json_success( $data )
and wp_send_json_error( $data )
. These helpers take any arbitrary data you send to them, sends the correct JSON content type header, outputs a JSON representation of your data and then kills the request for you. In your Javascript callback, the data is then properly transformed into an object. The data is wrapped in an extra object with success and data parameters like this:
{
success: true,
data: {
this: "is from"
php: "and can"
be: "anything. This was an associative array"
}
}
The success parameter allows the success callback a simple way to see if the process was successful, instead of just that the request itself was successful.
Other Considerations
Ajax both complicated and simple. The idea is very simple. It’s a request for data. That’s it.
However the way that request is made and processed can vary considerably.
We discussed using admin-ajax.php
to process requests, which is often a good way to go for arbitrary requests. Another great way process some requests is registering endpoints with rewrite rules. The advantage here is that it allows for the caching of endpoints helping to mitigate possible server load issues in high scale environments. Cached endpoints are generally faster as well because they take less processing.
The example request I gave was a POST request. This could just as easily have been a GET request.
The rabbit hole goes very very deep, but it’s worth exploring and getting comfortable with. So come on in, send some requests, and make things happen. It’s a valuable skill to have.
May 4, 2015 at 1:08 am
Please Provide full code
May 4, 2015 at 7:40 am
The full code is pretty much all in the article(s). I refrained from posting the code in it’s entirety, though, because this is an iterative example, not really something that should be used wholesale. Are you looking for reference, or for use?