Languages: English • in Plugins 日本語 한국어 • (Add your language)
This article, aimed at plugin developers, describes how to add Ajax to a plugin. Before reading this article, you should be familiar with the following:
If you're looking to use Ajax with the Gutenberg editor, please refer to the [1](Gutenberg Handbook).
Since Ajax is already built into the core WordPress administration screens, adding more administration-side Ajax functionality to your plugin is fairly straightforward.
This short example uses PHP to write our JavaScript in the footer of the page. This script then triggers the AJAX request when the page is fully loaded:
<?php
add_action( 'admin_footer', 'my_action_javascript' ); // Write our JS below here
function my_action_javascript() { ?>
<script type="text/javascript" >
jQuery(document).ready(function($) {
var data = {
'action': 'my_action',
'whatever': 1234
};
// since 2.8 ajaxurl is always defined in the admin header and points to admin-ajax.php
jQuery.post(ajaxurl, data, function(response) {
alert('Got this from the server: ' + response);
});
});
</script> <?php
}
Then, set up a PHP function to handle the AJAX request.
<?php add_action( 'wp_ajax_my_action', 'my_action' ); function my_action() { global $wpdb; // this is how you get access to the database $whatever = intval( $_POST['whatever'] ); $whatever += 10; echo $whatever; wp_die(); // this is required to terminate immediately and return a proper response }
Notice how the 'action' key's value 'my_action', defined in our JavaScript above, matches the latter half of the action 'wp_ajax_my_action' in our AJAX handler below. This is because it is used to call the server side PHP function through admin-ajax.php. If an action is not specified, admin-ajax.php will exit, and return 0
in the process.
You will need to add a few details, such as error checking and verifying that the request came from the right place ( using check_ajax_referer() ), but hopefully the example above will be enough to get you started on your own administration-side Ajax plugin.
Notice the use of wp_die(), instead of die() or exit(). Most of the time you should be using wp_die() in your Ajax callback function. This provides better integration with WordPress and makes it easier to test your code.
The same example as the previous one, except with the JavaScript on a separate external file we'll call js/my_query.js. The examples are relative to a plugin folder.
jQuery(document).ready(function($) { var data = { 'action': 'my_action', 'whatever': ajax_object.we_value // We pass php values differently! }; // We can also pass the url value separately from ajaxurl for front end AJAX implementations jQuery.post(ajax_object.ajax_url, data, function(response) { alert('Got this from the server: ' + response); }); });
With external JavaScript files, we must first wp_enqueue_script() so they are included on the page. Additionally, we must use wp_localize_script() to pass values into JavaScript object properties, since PHP cannot directly echo
values into our JavaScript file. The handler function is the same as the previous example.
<?php add_action( 'admin_enqueue_scripts', 'my_enqueue' ); function my_enqueue($hook) { if( 'index.php' != $hook ) { // Only applies to dashboard panel return; } wp_enqueue_script( 'ajax-script', plugins_url( '/js/my_query.js', __FILE__ ), array('jquery') ); // in JavaScript, object properties are accessed as ajax_object.ajax_url, ajax_object.we_value wp_localize_script( 'ajax-script', 'ajax_object', array( 'ajax_url' => admin_url( 'admin-ajax.php' ), 'we_value' => 1234 ) ); } // Same handler function... add_action( 'wp_ajax_my_action', 'my_action' ); function my_action() { global $wpdb; $whatever = intval( $_POST['whatever'] ); $whatever += 10; echo $whatever; wp_die(); }
Since WordPress 2.8, there is a hook similar to wp_ajax_(action):
So, if you want it to fire on the front-end for both visitors and logged-in users, you can do this:
add_action( 'wp_ajax_my_action', 'my_action' ); add_action( 'wp_ajax_nopriv_my_action', 'my_action' );
Note: Unlike on the admin side, the ajaxurl
javascript global does not get automatically defined for you, unless you have BuddyPress or another Ajax-reliant plugin installed. So instead of relying on a global javascript variable, declare a javascript namespace object with its own property, ajaxurl
. You might also use wp_localize_script() to make the URL available to your script, and generate it using this expression: admin_url( 'admin-ajax.php' )
Note 2: Both front-end and back-end Ajax requests use admin-ajax.php so is_admin() will always return true in your action handling code. When selectively loading your Ajax script handlers for the front-end and back-end, and using the is_admin() function, your wp_ajax_(action) and wp_ajax_nopriv_(action) hooks MUST be inside the is_admin() === true part.
Ajax requests bound to either wp_ajax_ or wp_ajax_nopriv_ actions are executed in the WP Admin context. Carefully review the actions you are performing in your code since unprivileged users or visitors will be able to trigger requests with elevated permissions that they may not be authorized for.
if ( is_admin() ) { add_action( 'wp_ajax_my_frontend_action', 'my_frontend_action' ); add_action( 'wp_ajax_nopriv_my_frontend_action', 'my_frontend_action' ); add_action( 'wp_ajax_my_backend_action', 'my_backend_action' ); // Add other back-end action hooks here } else { // Add non-Ajax front-end action hooks here }
Here the Ajax action my_frontend_action will trigger the PHP function my_frontend_action_callback() for all users. The Ajax action my_backend_action will trigger the PHP function my_backend_action_callback() for logged-in users only.
Plugins and themes that insert content via Ajax must trigger the post-load
event on document.body
after content is inserted. Other scripts that depend on a JavaScript interaction after content insertion, such as AddToAny or a jQuery Masonry script, listen for the post-load
event to initialize their required JavaScript. When the post-load
event is fired from Jetpack's Infinite Scroll, for example, AddToAny displays the share buttons for each post, and jQuery Masonry positions elements on the page.
JavaScript triggering the post-load
event after content has been inserted via Ajax:
jQuery( document.body ).trigger( 'post-load' );
JavaScript listening to the post-load
event:
jQuery( document.body ).on( 'post-load', function () { // New content has been added to the page. } );
Note on jQuery: Beware of using jQuery's load
method with a selector expression to insert content because it will cause <script>
blocks in the response to be stripped out.
If the Ajax request fails in wp-admin/admin-ajax.php, the response will be -1 or 0, depending on the reason for the failure. Additionally, if the request succeeds, but the Ajax action does not match a WordPress hook defined with add_action('wp_ajax_(action)', ...) or add_action('wp_ajax_nopriv_(action)', ...), then admin-ajax.php will respond 0.
To parse AJAX, WordPress must be reloaded through the admin-ajax.php script, which means that any PHP errors encountered in the initial page load will also be present in the AJAX parsing. If error_reporting is enabled, these will be echoed to the output buffer, polluting your AJAX response with error messages.
Because of this, care must be taken when debugging Ajax as any PHP notices or messages returned may confuse the parsing of the results or cause your JavaScript to error.
One option if you can't eliminate the messages and must run with debug turned on is to clear the buffer immediately before returning your data.
ob_clean(); echo $whatever; wp_die();
It is also possible to use tools such as FirePHP to log debug messages to your browsers debug console. An alternative approach is to use a debugging proxy such as fiddler.