AJAX is used in many WordPress themes and plugins. However, not all of those themes and plugins implement AJAX properly. This article reveals 5 best practices in developing AJAX for WordPress.
Warning: This is a long and information-packed article. Be sure to bookmark this post so you can always go back for reference! The links below makes it easier to navigate this article.
Table of Content
- Bad ways to implement AJAX
- 1. Use wp_localize_script() to declare javascript global variables
- 2. Use admin-ajax.php to handle AJAX requests
- 3. Use nonces and check for permission
- 4. Use the built-in jQuery Form plugin to submit forms
- 5. Be careful with jQuery default JSON parsing
Bad ways to implement AJAX
I have read the code of many plugins that implement AJAX. While some of them do it the right way, most of them don’t. The common pattern in those plugins is: a PHP file to handle the AJAX request, and another PHP file that spits out javascript code to make the AJAX request.
The PHP file that handles the AJAX almost always begin with this line:
require_once( "../../../../wp-config.php" ); // or require_once( "../../../../wp-load.php" );
What’s wrong with this is that sometimes users set up their folder structure differently, making the relative path declared in the PHP file above invalid. Another downside to this, is if you’re using Object Oriented approach to develop your plugin (wrapping your plugin functions in a class), you won’t have direct access to the necessary properties and private functions of the class.
Along with the PHP file above, another PHP file is necessary to output the javascript that makes the AJAX request. This has to be a PHP file instead of a normal JavaScript file, because (again) it has to include wp-config.php (or wp-load.php), so that it can get the absolute URL to the PHP file that handles the request, or load some additional data from the database. In order to load this “fake” javascript file, the whole WordPress framework needs to be loaded again.
Sorry for keeping you off the good part of the article so long. But avoiding doing things the wrong way is as important as knowing how to do them right. Without further ado, here are 5 crucial tips for implementing AJAX in WordPress properly.
1. Use wp_localize_script() to declare javascript global variables
Although wp_localize_script() is created for localization, it also has another great use. You can declare javascript variables with namespaces to use with your script. Here’s the syntax:
wp_localize_script( $handle, $namespace, $variable_array );
Here’s how you should declare the URL to the file that handles AJAX (in this example, I use admin-ajax.php, which is discussed in tip #2):
// embed the javascript file that makes the AJAX request wp_enqueue_script( 'my-ajax-request', plugin_dir_url( __FILE__ ) . 'js/ajax.js', array( 'jquery' ) ); // declare the URL to the file that handles the AJAX request (wp-admin/admin-ajax.php) wp_localize_script( 'my-ajax-request', 'MyAjax', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) );
This way, you won’t have to use PHP to print out JavaScript code, which is both ugly and non-cacheable. If you take a look at the generated HTML in the <head> element, you’ll find this:
<script type="text/javascript" src="http://example.com/wordpress/wp-content/plugins/myajax/js/ajax.js"></script>
<script type="text/javascript">
/* <![CDATA[ */
var MyAjax = {
ajaxurl: "http://example.com/wordpress/wp-admin/admin-ajax.php"
};
/* ]]> */
</script>
Now, in your ajax.js file, you can use MyAjax.ajaxurl without having to resort to PHP and including wp-load.php. Please refer to tip #2 below for more about setting up the javascript code that sends the request, and how to handle the request properly.
2. Use admin-ajax.php to handle AJAX requests
AJAX requests should be directed to wp-admin/admin-ajax.php. I know the “admin” part of the file name is a bit misleading, but all requests in the front-end (the viewing side) as well as the admin panel can be processed in admin-ajax.php.
There’s a required parameter for a request sent to admin-ajax : it’s called action. This parameter is necessary because when admin-ajax process the request, it will fire one of these hooks, depending on whether the current viewer is logged in or not:
// this hook is fired if the current viewer is not logged in do_action( 'wp_ajax_nopriv_' . $_REQUEST['action'] ); // if logged in: do_action( 'wp_ajax_' . $_POST['action'] );
The JavaScript code that submits the AJAX request should look something like this:
jQuery.post(
// see tip #1 for how we declare global javascript variables
MyAjax.ajaxurl,
{
// here we declare the parameters to send along with the request
// this means the following action hooks will be fired:
// wp_ajax_nopriv_myajax-submit and wp_ajax_myajax-submit
action : 'myajax-submit',
// other parameters can be added along with "action"
postID : MyAjax.postID
},
function( response ) {
alert( response );
}
);
Now all we have to do is hook our existing plugin or theme file up with those provided ajax actions without having to create a separate file to process the request:
// if both logged in and not logged in users can send this AJAX request,
// add both of these actions, otherwise add only the appropriate one
add_action( 'wp_ajax_nopriv_myajax-submit', 'myajax_submit' );
add_action( 'wp_ajax_myajax-submit', 'myajax_submit' );
function myajax_submit() {
// get the submitted parameters
$postID = $_POST['postID'];
// generate the response
$response = json_encode( array( 'success' => true ) );
// response output
header( "Content-Type: application/json" );
echo $response;
// IMPORTANT: don't forget to "exit"
exit;
}
3. Use nonces and check for permission
It can’t be stressed enough that you need to check for permission for every action a user takes. Developers often neglect this, and the results are disastrous, because without layers that checks for sufficient permissions, a malicious user could escalate his privilege and do all sorts of naughty things with your website that you have spent so much effort to build. There are two layers of security that you need to apply to all AJAX request most of the time.
Nonces
Nonces are Numbers that are generated and used once. Nonces are used to make sure the action is initiated by the authorized user from a certain location. Here’s an interesting analogy by Jon Sykes, which makes everything easier to understand:
When you arrive at a deli counter you’re asked to take a ticket. Once the counter reaches your number you had the ticket back to the server (who throws it away) and they serve you. They then move onto serving the next person in the who’s ticket matches the number of the digital screen.
If someone comes along and tries to jump the line (queue) they can’t unless they have a ticket.
If they manage to get hold of someones old ticket, they can’t use it, as it’s already been used and the digital counter has moved on.
To further extend the analogy, you then make every customer sign for the ticket when they take one, and you then check not only that there ticket matches but also make them sign again to check that their first signature matches the one they have before they get served.
Taking it to a silly level, you’d only allow users to get a ticket when they walked in the front door of the store (that they have to sign for). This then prevents someone climbing in a window and trying to forge your signature to get served. Because they didn’t come in the front door, they don’t have any access to the tickets, so they have no way of jumping ahead of you and ordering the last of the Bologna.
Mark Jaquith and Vladimir Prelovac also covered Nonces and how to use them generally. Make sure you read those articles because you’ll definitely need them for almost all kinds of WP development (not only AJAX related).
However, it should be stressed that nonces are useful only in situations where the AJAX request has something to do with data or content manipulation. If the request is only for retrieving comment count, or post content for example, nonces are not required. AJAX requests to post / edit / delete contents definitely need nonce checking.
OK, enough theory. Here’s how to implement nonces in your AJAX request.
First, you need to generate a nonce, and use wp_localize_script() to include it as a javascript variable:
// embed the javascript file that makes the AJAX request wp_enqueue_script( 'my-ajax-request', plugin_dir_url( __FILE__ ) . 'js/ajax.js', array( 'jquery' ) ); wp_localize_script( 'my-ajax-request', 'MyAjax', array( // URL to wp-admin/admin-ajax.php to process the request 'ajaxurl' => admin_url( 'admin-ajax.php' ), // generate a nonce with a unique ID "myajax-post-comment-nonce" // so that you can check it later when an AJAX request is sent 'postCommentNonce' => wp_create_nonce( 'myajax-post-comment-nonce' ), ) );
Now your JavaScript can use the global variable MyAjax.postCommentNonce to get the nonce. You have to send the nonce along with your request so that the AJAX handler can check it:
jQuery.post(
MyAjax.ajaxurl,
{
action : 'myajax-submit',
postID : MyAjax.postID,
// send the nonce along with the request
postCommentNonce : MyAjax.postCommentNonce
},
function( response ) {
alert( response );
}
);
Here’s essentially the same code as in tip #2, except that I’ve added nonce validation to make sure the request is valid:
// if both logged in and not logged in users can send this AJAX request,
// add both of these actions, otherwise add only the appropriate one
add_action( 'wp_ajax_nopriv_myajax-submit', 'myajax_submit' );
add_action( 'wp_ajax_myajax-submit', 'myajax_submit' );
function myajax_submit() {
$nonce = $_POST['postCommentNonce'];
// check to see if the submitted nonce matches with the
// generated nonce we created earlier
if ( ! wp_verify_nonce( $nonce, 'myajax-post-comment-nonce' ) )
die ( 'Busted!')
// get the submitted parameters
$postID = $_POST['postID'];
// generate the response
$response = json_encode( array( 'success' => true ) );
// response output
header( "Content-Type: application/json" );
echo $response;
// IMPORTANT: don't forget to "exit"
exit;
}
There, all done. Now here’s an important note. If you want to allow the user to initiate the AJAX request multiple times (like posting multiple comments on the same page) , you need to regenerate a new nonce, include it in your response, and then reassign that new nonce to MyAjax.postCommentNonce. Otherwise, the same nonce would be used over and over again, and the subsequent AJAX requests will fail.
Check for permissions
Lots of plugins neglect to check for sufficient permission for AJAX requests. Always use current_user_can() to make sure the request is made by an authorized user. Here’s the final bulletproofed version of the request handling code:
// if both logged in and not logged in users can send this AJAX request,
// add both of these actions, otherwise add only the appropriate one
add_action( 'wp_ajax_nopriv_myajax-submit', 'myajax_submit' );
add_action( 'wp_ajax_myajax-submit', 'myajax_submit' );
function myajax_submit() {
$nonce = $_POST['postCommentNonce'];
// check to see if the submitted nonce matches with the
// generated nonce we created earlier
if ( ! wp_verify_nonce( $nonce, 'myajax-post-comment-nonce' ) )
die ( 'Busted!')
// ignore the request if the current user doesn't have
// sufficient permissions
if ( current_user_can( 'edit_posts' ) ) {
// get the submitted parameters
$postID = $_POST['postID'];
// generate the response
$response = json_encode( array( 'success' => true ) );
// response output
header( "Content-Type: application/json" );
echo $response;
}
// IMPORTANT: don't forget to "exit"
exit;
}
4. Use the built-in jQuery Form plugin to submit forms
Most of the time you use AJAX to avoid page reload when submitting forms. Not everyone knows that WordPress also provide a jQuery plugin to deal with AJAX form submission. To use this jQuery plugin, include it by using “jquery-form” as the handle:
wp_enqueue_script( 'json-form' );
Then, submitting form using AJAX is a breeze:
jQuery('#myForm1').ajaxForm({
data: {
// additional data to be included along with the form fields
},
dataType: 'json',
beforeSubmit: function(formData, jqForm, options) {
// optionally process data before submitting the form via AJAX
},
success : function(responseText, statusText, xhr, $form) {
// code that's executed when the request is processed successfully
}
});
There are a lot more options for you to configure. Check out jQuery Form plugin documentation for more details.
5. Be careful with jQuery default JSON parsing
At the moment of this writing, the latest stable version of WordPress is 2.9.2 . In this version of WordPress, the default jQuery version is 1.3.2 .
In jQuery 1.3.2 or earlier, jQuery uses eval to convert a JSON string into an object. While this is fast, it’s not safe:
The eval function is very fast. However, it can compile and execute any JavaScript program, so there can be security issues. The use of eval is indicated when the source is trusted and competent. It is much safer to use a JSON parser. In web applications over XMLHttpRequest, communication is permitted only to the same origin that provide that page, so it is trusted. But it might not be competent. If the server is not rigorous in its JSON encoding, or if it does not scrupulously validate all of its inputs, then it could deliver invalid JSON text that could be carrying dangerous script. The eval function would execute the script, unleashing its malice.
from json.org
jQuery 1.3.3 and later will automatically check if there’s already a JSON parser, and use that parser instead of eval(). WordPress also provides the javascript JSON parser in wp-includes/js/json2.js. Including it is simple:
wp_enqueue_script( 'json2' );
Then, to make sure your script parses JSON the safe way, there are two ways:
The first way is to include your own version of jQuery (equal or later than 1.3.3)
wp_enqueue_script( 'json2' ); // don't forget to specify dependency wp_enqueue_script( 'myjQuery', plugin_dir_url( __FILE__ ) . 'js/jquery.1.4.2.js', array( 'json2' ) );
The second way is to use WordPress supplied jQuery, but make sure that you don’t specify “json” as the response type, and use the included JSON parser to do the dirty job. You need to set the dependency first:
// embed the javascript file that makes the AJAX request // don't forget to specify 'json2' as the dependency wp_enqueue_script( 'my-ajax-request', plugin_dir_url( __FILE__ ) . 'js/ajax.js', array( 'jquery', 'json2' ) );
Then use JSON parser to parse the response string:
jQuery.post( MyAjax.ajaxurl, { action : 'myajax-submit' },
function( jsonString ) {
// use JSON parser on the response string instead of
// specifying the response type as json
var object = JSON.parse(jsonString);
}
);
Conclusion
AJAX makes interaction with users more smooth and responsive, and is highly recommended for consideration when you develop your own plugins or themes. However, it’s vital that AJAX is implemented correctly and securely, otherwise the consequence could be disastrous. This article covers 5 most essential tips that all serious WordPress developers should employ to make sure their AJAX plugins or themes function well and safe.
Do you have other AJAX tips or tricks that you want to share? Drop in a comment below. Your input is always appreciated!
This stuff is really hardcore, you’ve selected the domain very well..
Thanks! I’m glad you liked the article.
I still have a lot to improve on explaining things, so if there’s anything that needs more clarification, please let me know
I think your jQuery Form plugin section will be the most rewarding for myself as that is one thing I have been struggling with for a while now.
Thanks for the info.
While I use admin-ajax.php for my admin-side AJAX stuff, my preference for AJAX on the frontend has been the following:
`function my_ajax_stuff() {
if (isset($_GET["my_ajax_action"])) {
// DO AJAX STUFF HERE
exit();
}
}
add_action( ‘wp’, ‘my_ajax_stuff’ );`
My main reason for this over admin-ajax with a _nopriv_ action was to accomodate clients who have wp-admin/ folder IP or password restricted via .htaccess
Any comments on this as an approach?
I personally think setting up .htaccess restricted password for wp-admin folder is an overkill. You should actually recommend them against using such method.
However I do agree that having a PHP file in wp-admin to process AJAX requests for non-privileged users is a huge drawback of this approach. I will do some more research and probably submit a ticket on WordPress trac system and ask if any core developers are willing to fix this.
In the mean time, your method of detecting AJAX request via $_GET works as well (although I recommend doing it via $_POST instead).
Yeah – there probably should be an ajax.php in the site root, in addition to wp-admin/admin-ajax.php
GET vs POST – I use differing approaches depending on the context, generally following the “If it does something rather than just retrieving something then use POST, otherwise GET” guidelines. My example just happened to use GET
Lee, I’m currently working on a Ajax-based plugin that adds some images fades and whatnot to the theme. I initially used the method that you outlined here, but for some strange reason there was always two ajax responses one with 404 and anther with a 301. When I switched to using _nopriv_ only one request was returned. Have you ever experienced this in your projects?
I don’t get the “if you’re using Object Oriented approach to develop your plugin, you won’t have direct access to the necessary properties and private functions of the class”
Really nice article anyway. Didn’t know this site yet, will check it
(I may be worth mentioning that json_* functions are PHP 5.2+ which is much newer than WP requirements as of writing)
Thanks for your comments!
There are two approaches for organizing your plugin functions. One is procedural approach:
define( 'MY_PLUGIN_CONSTANT', 'some value' ); add_action( 'some_action', 'myplugin_some_action_handler' ); function myplugin_some_action_handler() { // code that executes when "some_action" is fired }The other is Object Oriented approach, which encapsulates all plugin functions into a class:
class MyPlugin { // private variables can be used private $private_var = 'some value'; function __construct() { // constructor add_action( 'some_action', array( $this, 'action_handler' ) ); } private function my_private_method() { // this method can only be called by another object method // but cannot be accessed anywhere outside this class } function action_handler() { // call a private method $this->my_private_method(); } }If you use the OO approach, obviously you can’t access or call private methods and variables conveniently outside the class.
I will write another article, evaluating the pros and cons of each approach.
About
json_encode(), fortunately WordPress also provided a fallback function with the same name in case the user is not using PHP 5.2+ :wp-includes/compat.php (line 127). So I guess it’s safe to use that function now.Please feel free to subscribe and come back anytime! I still have a bunch of hand-written notes that haven’t been published yet.
If you use OO correctly, you shouldn’t need to access private variables or functions directly.
Yes that’s right. That’s why using admin-ajax.php and wp_ajax hooks are the correct way to do it if you use OO.
Great hardcore articles, thank you! I tried to make AJAX calculator some weeks ago and now I can see that there were some mistakes… I had also one problem. AJAX calculator worked on website example.com well, but when users came from alias domain example.org there was Javascript error. It was probably caused by browser XHR restrictions, but I could not find a way to make it work also for alias. Do you have any idea how to do it? Thank you very much for your help…
I’m glad you like this article!
Unfortunately, I don’t know any work around for your situation yet, since it’s domain alias and I have never been in that situation before. I can point you into another direction though:
http://www.ajax-cross-domain.com/
Try it out and let me know if it works
Found a solution for you, which jQuery also provides built-in support for:
http://www.ibm.com/developerworks/library/wa-aj-jsonp1/
This is seriously WordPress hardcore tutorial.
At first I tried to use ajax using “admin-ajax.php” approach. It worked but only when you’re logged in as a admin user if you’re not logged in admin section it didn’t work so I ended up using bad approach??
Any idea why “admin-ajax.php” required admin authentication, I might did something wrong with it ??
BTW please use subscribe to comment Plugin of WordPress so that i can subscribe it via email ???
Hi, thanks for commenting!
A bit more clarification about admin-ajax.php :
I do agree it’s misleading to name the file admin-ajax.php, but that file is also capable of processing requests from a non-privileged user, if you set up your request correctly (an “action” parameter must be sent).
As noted in the article, there are two hooks you can use:
- wp_ajax_{your_action} to process requests made by already logged-in users
- wp_ajax_nopriv_{your_action} to process requests made by user who hasn’t logged in.
Please also take a look at WordPress documentation about using AJAX in plugin, which provides even more details. Hope this helps
I’ll also enable comment subscription asap.
Super article. Been looking for a nice base to start coding from.
Been rogue-ing my ajax for some time now, never to sure if I am doing it right. At least i was not in the no-no bin.
Thanks again.
You’re welcome !
I’m glad this article helped you.
excellent article!
Thanks! More cool stuff coming soon.
Hi,
nice article! Hope to read more such stuff on this site in the future
Some things to note (also regarding a few of the comments above) for an eventual update after WP 3.0 comes out:
- WP 3.0 has a file wp-ajax.php in the root folder, that should be used for frontend AJAX. There’s no need to use admin-ajax.php from the frontend anymore then.
It also has a new function “wp_ajaxurl()” that will add the ajaxurl JS variable to the head section automatically.
- I really disagree with your opinion about .htaccess security for the wp-admin directory and don’t understand why you are actually discouraging people from using it. It is a great and easy way to add more security actually. (E.g. keep in mind that brute force attacks against the regular wp-login.php screen will trigger a lot of DB queries…)
- For the nonce checks: You should use check_ajax_referer(), which is recommended over a direct use of wp_verify_nonce().
- And I also don’t get your objections to the OO approach. Where would I not have access to my class methods/variables if everything I have is in my class?
Anyway, again thanks for the article which I hope a lot of people read, so that we can benefit from better AJAX plugins
Best wishes,
Tobias
Hi Tobias,
Thanks for commenting!
The new changes in WP 3.0 are exactly what we need! Thanks for letting me know. I’ll definitely update this article when a release candidate is out.
About .htaccess protection of wp-admin: Yes, .htaccess password protection is a great way to prevent bruteforce attacks. I just don’t think it would be convenient for my clients if they have to enter passwords twice to get into the dashboard. More over, if the htpasswd file does not have adequate protection, your password can be revealed. The easier way to prevent bruteforce attack is using a plugin. There are several plugins out there than can limit the number of trials, or block an IP range in case of too many failed login attempt. Here’s a great round up of those plugins: http://www.techmynd.com/protect-wordpress-login-page-plugins-and-hacks/ .
However, this is totally depending on each developer’s preference. .htpasswd and .htaccess protection can work great if you are sure that you can configure it correctly (it’s best to keep the htpasswd file outside of the document root). I develop websites for clients who have limited knowledge about this thing, so it’s better for me to make it easier for my clients as well.
- I totally agree with you about check_ajax_referer() . Both functions work, although a bit differently. To use check_ajax_referer() with AJAX, most of the time you’ll also need to specify the second argument as the name of the nonce field. Documentation here: http://codex.wordpress.org/Function_Reference/check_ajax_referer . Thanks for pointing that out!
- About OO, I apologize if my explanation in the post confused you. I didn’t say I’m against the OO approach. As a matter of fact, I’m using the OO approach for all of my plugins and themes. What I tried to explain is that if you use OO approach, and do AJAX the bad way, you won’t have access to your private members of the plugin class. Using admin-ajax.php and wp_ajax hooks, you won’t have any problems calling private methods. Remember: not all of your instance methods should be made public.
Phew! That’s a long comment I wrote there. Thanks for your constructive criticism. I’m looking forward to having your feedback for my upcoming blog posts as well.
Hi,
you are sure welcome for the comment and I will try to leave feedback for your upcoming posts, of course!
Regarding .htaccess: Yes, it might be too much for a site with several non-experts or clients, but as a developer, I really like the solution. The .htpasswd location should of course be non-accessible, but even if the attacker gets access to it: The password for the .htaccess should of course be a different one than the actual WP password
For check_ajax_admin(): Actually it is the other way around: You don’t have to specify the name of the nonce argument (the function will try “_ajax_nonce” and “_wpnonce” then). And you actually have to know the name of the argument in your case, too (line 8 of that one code block). But it might just be a matter of personal preference.
And thanks for the explanation on what you meant regarding OO. Makes it clearer now
And I guess if someone really uses classes with actual private/public methods (and not just for avoiding the duplicate function name issue), he should also be able to do the AJAX correctly.
Ok. I’m looking forward to your next article
Regards,
Tobias
Hi,
it looks like my suggestion on wp-ajax.php and wp_ajaxurl() is no longer valid. The feature was removed again from core, due to security concerns (see Ticket #12400 in Trac).
Instead, admin-ajax.php is the correct way to go (but might require some special love for frontend AJAX).
Regards,
Tobias
its really a nice article on admin-ajax.. A bit elaboration with exmaple is really needed in this case .
Thanks for commenting. Please let me know which part of the article you want me to explain in more details
Great article Gary, it is refreshing to see a post where this technique so often done incorrectly is done right Congrats on the new blog and kicking it off in wonderful style with this article. Subscribing!
Thanks! I’m working on a big blog post right now. Can’t wait until finally publishing it. Stay tuned!
You made it right into my “Must Read” folder of feeds. Looking forward to new content!
Thanks. That’s a nice Portfolio you got on your site!
Hello,
First, thanks a lot for these very helpfull tips.
I tried to use admin-ajax.php to handle my ajax requests … but it’s very slow. I tried to use Firebug to trace the time spent and it takes approx 7 seconds to retrieve 4 records in a database (just a select * + json in my ajax hook) on my Synology NAS.
I think it’s not due to the hook because if I replace my code by a simple echo, it takes approx the same time.
I suspect admin-ajax to consume time. Any tips to increase speed ?
useful informative article…
Thanks for sharing this post.
Man, you have no idea how I wished this stuff was written two years ago. To have such resources pooled into one article is so helpful and convenient.
I remember having to search and read numerous articles, forum postings and digging into the codes to do AJAX in plugins.
Ehem .. Sorry, BUT: There never was a jQuery version such as v1.3.3. Maybe you’re confusing it with 1.2.3?
Just take a look for yourself at the “past version” download corner @ jquery.com: http://docs.jquery.com/Downloading_jQuery#Past_Releases
cu, w0lf.
Thanks for the comment.
There was a jQuery 1.3.3, however I don’t know why but it was not publicly released, and the version number jumped right to v1.4 . The information in the article is still relevant though, as WordPress 2.9.2 is still using jQuery 1.3.2.
Perhaps it was only a developmental version, and because there were too many changes they decided to make it 1.4 instead. Anyone knows the details about this?
Anyways, in the Roadmap, they do mention 1.3.3: http://docs.jquery.com/JQuery_1.4_Roadmap
Why wordpress made ajax handling so complicated ?
just one suggestion, after reading such a long post, if I want to navigate to any other link in header, I have to scroll up at least 10 to 15 times to reach header. So it is better if you add a “Back to top” link at the end of post and comments.
Well, it’s actually not that complicated. Handling the request is simple, just hook it up. The part that matters is how to make it secure, and I believe you run into the same problem with every other CMS. It’s not easy to make your plugin bullet-proofed.
Thanks for the suggestion regarding the “back to top” link. I’m experimenting with a plugin that lets me do something about it. If it doesn’t work, I’ll just do it manually.
Thanks for article!
I have one problem, i tried code with nonces, but it seem that when i do multiple request it works without need of refreshing nonce. Do i something wrong? It seems to me that i can go to cinema with one ticket multiple times
Hi there, i’am having problem with AJAX implementation in the plugin that i’am currently working on.
this my effort so far (just for testing ajax output):
function my_ajax() {echo ‘blala’; die();}
add_action(‘wp_ajax_my_ajax’, ‘my_ajax’);
the javascript:
$(‘a#ajax’).click(function() {
$.ajax({type:’POST’,url:ajaxurl,data:post_values,success:function(msg){alert(msg)}});
});
Just wanted to thank you for the detailed how-to/tips, helped me a lot with my project
Pingback: Best of Amazing jQuery Tutorials April 2010 « Defonic International Solutions
Excellent article! Thanks a lot!
I encountered some problems regarding the scopy of some global variables that are not available in an AJAX call… it would be great to read a followup of this article regarding this kind of issues.
Thus, I would like to add my tiny two cents…
You will probably have some include files that you just need in order to perform the AJAX process (including the very declarations of the add_action’s)…
As they are only required inside an AJAX call, they only add unnecessary load to your plugin… so I recommend to put them inside a conditional that check for the DOING_AJAX constant:
if ( defined(‘DOING_AJAX’) && DOING_AJAX ) {
// do stuff needed inside an AJAX call…
}
I hope it helps,
Will
This helped me a lot. Thanks for the summary. It’s unfortunate that new front-end ajax handling is scratched from WP 3.0, however, remembering to use the wp_ajax_nopriv_… hook and using wp_localize_script() to define a variable reference to admin-ajax.php makes front-end ajax way smoother than how I did it before.
Just wanted to say thanks for this. I’ve been referencing back to it all weekend.
Thanks for the tips! we really need high quality posts like this.
Pingback: Google Calendar Events, 0.3.1 « Ross Hanney
CWbrgm http://cgE8hcmk9Vvqlosr5wcBa6nk.com
Hello,
Thanks for your great post, it help a lot !
Do you know if it’s possible to have more than one hook for ajax request like this :
add_action( ‘wp_ajax_nopriv_myajax-submit-one’, ‘myajax_submit_one’ );
add_action( ‘wp_ajax_myajax-submit-one’, ‘myajax_submit_one’ );
function myajax_submit_one() {
// do request
}
add_action( ‘wp_ajax_nopriv_myajax-submit-two’, ‘myajax_submit_two’ );
add_action( ‘wp_ajax_myajax-submit-two’, ‘myajax_submit_two’ );
function myajax_submit_two() {
// do request
}
Because I trying a like thing in a plug-in and get “-1″ responses from the second ajax request…
It make feel that we can just use one hook and we must adapt responses for deferent request in it’s callback or I’m missing something !
Sorry !
We can do that, having just a problem with the nonce check for the second request…
Thanks !
[url]http://frederickcomputer.com[/url]
Thanx soo much for the tip with the wp_localize_script!!! I searched so long for how to get those URLs to my jquery file and now it is easy as a breeze!!!
Interesting that you are going against the official Hardening WordPress article, which has a section on Securing wp-admin.
Regardless, if you use wp-admin/admin-ajax.php for client facing AJAX, in a plugin or theme that you plan to release, a percentage of your users are going to be delivering a password dialog to their visitors on each Ajax call. Bad Bad Bad.
Also be aware that using Nonces appears to break if you’re using a Caching plugin (WP Super Cache, W3 Total Cache, etc). While I agree nonce’s should be used in general, if you release a plugin or theme that noncifies Ajax calls, then this isn’t going to work for some of your users (and more and more people are using a caching plugin).
Hello and thanks for this tutorial ! I really learn a lot form this.
But still I notice a tiny little error in Step 4 about the build-in jQuery Form plugin.
Your code is
wp_enqueue_script( ‘json-form’ );
when I think it should be :
wp_enqueue_script( ‘jquery-form’ );
That’s just my little feedback, and thanks again for this very usefull article
Thanks, I couldn’t get my AJAX to parse until I changed
responsetojsonString.Awesome!
Pingback: 40 Very Useful Wordpress Tutorials Help You Become an Expert - Ntt.cc
Talk about an understatement. Hardcore? This is a bit past that, at least for some of us who thought Ajax was something for later!
Nice article. Will check the site more often.
Thanks
Hello,
What a great article! I found it very hard to find something decent on ajax and wordpress. Thanks a lot!
I’m trying to add an ajax form to a meta box at a custom post type edit screen. However, I can’t figure out how to make it work. The explanation of my problem is a bit big for a comment, please have a look here http://tiny.cc/jniz1 I’m explaining what I’m trying to do and where I’m stuck.
I would really appreciate if you could give me some tips on how to proceed. I’ve been trying to figure it out for over a week now with no luck.
Many thanks,
Dasha
Thanks for a great article. I have a question regarding what you write about regenerating the nonce, where you write:
“you need to regenerate a new nonce, include it in your response, and then reassign that new nonce to MyAjax.postCommentNonce. Otherwise, the same nonce would be used over and over again, and the subsequent AJAX requests will fail.”
This is what I would have thought too, but it seems that the nonce is not made unuseable after it has been checked (like the ticket analogy) but can be used several times within a 24 hour time window. Is this correct? I get the same nonce everytime i generate it, and I can use that same nonce multiple times..
Did I misunderstand something, or is this actually the way it works?
Hi Gary, heres an encouragement to write that article “evaluating the pros and cons of each [OO vs. procedural] approach you mention. I’ve been researching the issue and would like some more thoughts on this. OO just seems to be the more professional and robust way of doing things, but given the context of the WP framework itself and the openness and learning curve considerations for newcomers, there are surely arguments against it as well.
Many uses of OO that I’ve seen recently merely uses the approach for anything besides the classes acting as namespaces. I think a lot of developers would benefit from more discussion regarding how to proper apply an OO approach in the context of WP development.
I’m not myself used to OOP and tend to go with Procedural as I find it being more familiar. though I do see the advantages of OO once you get your brain wrapped around it properly.
Recently I needed to create a slightly more advanced version of the native WP function update_option, and I wondered if there would have been a way to do this using OO and extending some WP option_handler class instead of simply creating an alternative function called my_update_option. See stackoverflow.com/questions/4134284/
Based on a quick look at /wp-includes/functions.php it does not seem that this functionalities are coded in OO style. What is your thoughts on developing in OO within a framework that is basically a Procedural environment, what are the benefits if you can’t inherit from or extend existing classes? And also, are ‘hooks’ not in a way an alternative to this within a procedural context?
I hope you find time to comment on these questions, and bear with me if they are formulated a little confusing, it is because I’m not really understanding OO yet.
People who want to achieve ajax request on a wordpress powered website should definetly give this a look http://wordpress.org/extend/plugins/json-api/.
very nice..
thanks for sharing..
it will be great for web development..
Excellent Tips. Thanks a lot
——————–
New Line Equity
This article is great. Highly recommended for plugin developers looking to beef up their support for AJAX. The addition of the nonce security bit was extremely well explained and very helpful. Keep up the good work!
wow, this is really great stuff! thanks for the info. just need to add the nonces part.
Hi,
Great article, but a bit difficult to understand for developpers that are not familliar with all the inner workings of wordpress.
It could be of great use, if you could explain in exactly which file every piece of code needs to be written.
I got the big picture that the admin-ajax.php is used, I have it open,but for example where do I need to add the first code snippet:
// embed the javascript file that makes the AJAX request
2 wp_enqueue_script( ‘my-ajax-request’, plugin_dir_url( __FILE__ ) . ‘js/ajax.js’, array( ‘jquery’ ) );
3
4 // declare the URL to the file that handles the AJAX request (wp-admin/admin-ajax.php)
5 wp_localize_script( ‘my-ajax-request’, ‘MyAjax’, array( ‘ajaxurl’ => admin_url( ‘admin-ajax.php’ ) ) );
Do I need to add it to the admin-ajax.php? I guess not, but then where in which file?
Great article though,
Thanks
Jimmyy
Nice article man! Thank you, Merry Xmas!
i usage
add_action(‘wp_ajax_myplugin’, array(&$this,’ajax’));
/
add_action(‘wp_ajax_nopriv_myplugin’, array(&$this,’ajax’));
I have a problem, I develop a plugin widget in the plugin adds a text output at each end of the record office, and there is a button in a form for sending Ajax requests sent from the home page constantly Ajax request is identified through is_admin () as true
any ideas?
ajax url http://my…site.com/wp-admin/admin-ajax.php
Yes, that’s because at the beginning of
admin-ajax.php, the constantWP_ADMINis defined astrue. This might be counter-intuitive, asadmin-ajax.phpcan be used on the front-end as well. You might want to file a ticket on WordPress Core Trac to mention this inconsistency to core developers.In the mean time, instead of
is_admin(), you can useis_user_logged_in().Hey Gary,
Thanks a ton for the great explication on good AJAX practices in WordPress. I’m actually having a problem with one ajax request unintentionally triggering another. I have a logout ajax function that is set up in admin-ajax.php as:
do_action( ‘wp_ajax_submit_logout’, $_REQUEST['action'] );
and a star rating function set up just below (using the handle from your example)
do_action( ‘wp_ajax_myajax-submit’, $_REQUEST['action'] );
Then I set up their respective add_action(‘ ‘) in the functions folder. The result: when I fire the star rating function, the AJAX request triggers the logout function as well !
I’m assuming it’s okay to have more than one AJAX hook set up in admin-ajax, right?
If you could tell me what I’m doing wrong, I’d be forever thankful !
Thanks !
Dan
You should use add_action() instead of do_action():
‘my_plugin_submit_logout’ and ‘my_plugin_star_rating’ are 2 functions that handle your request. ‘submit-logout’ and ‘star-rating’ are the action parameters of the request.
If you’re still stuck, please send me an email with your code (garyc40 [at] garyc40.com), I’ll try to help out as soon as I have some time
Very goooood tutorial!!!
It’s very helpfull