WordPress.org

Ready to get started?Download WordPress

Codex

AJAX in Plugins

Contents

Introduction

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:

  • Ajax - Overview of the technology
  • Writing a Plugin - How to write a plugin
  • Plugin API - Filters and actions - what they are and how to use them
  • How to add HTML to the appropriate WordPress page, post, or screen -- for instance, if you want to add Ajax to administration screens you create, you will need to understand how to add administration menus to WordPress; if you want to add Ajax to the display of a single post, you'll need to figure out the right filters and actions to add HTML to that spot on viewer-facing blog screens. This article does not cover these topics.

Ajax on the Administration Side

Since Ajax is already built into the core WordPress administration screens, adding more administration-side Ajax functionality to your plugin is fairly straightforward, and this section describes how to do it.

Here's a short example. All this will be in one file. First, add some javascript that will trigger the AJAX request:

<?php
add_action( 'admin_footer', 'my_action_javascript' );

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
	$.post(ajaxurl, data, function(response) {
		alert('Got this from the server: ' + response);
	});
});
</script>
<?php
}

Then, set up a PHP function that will handle that request:

<?php 

add_action( 'wp_ajax_my_action', 'my_action_callback' );

function my_action_callback() {
	global $wpdb; // this is how you get access to the database

	$whatever = intval( $_POST['whatever'] );

	$whatever += 10;

        echo $whatever;

	die(); // this is required to return a proper result
}

That's it! 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.

NOTE: Since Version 2.8, The javascript global variable ajaxurl can be used in case you want to separate your javascript code from php files into javascript only files. This is true on the administration side only.


Separate Javascript File

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 files, we must enqueue them in PHP so they are included on the page. 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_callback' );
function my_action_callback() {
	global $wpdb;
	$whatever = intval( $_POST['whatever'] );
	$whatever += 10;
        echo $whatever;
	die();
}

With external javascript files, we can't echo values into a script block, but we can use wp_localize_script() to pass values into javascript object properties.

Ajax on the Viewer-Facing Side

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_callback' );
add_action( 'wp_ajax_nopriv_my_action', 'my_action_callback' );

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_callback' );
    add_action( 'wp_ajax_nopriv_my_frontend_action', 'my_frontend_action_callback' );
    add_action( 'wp_ajax_my_backend_action', 'my_backend_action_callback' );
    // 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.

Error Return Values

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.

Debugging

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 imediately before returning your data.

    ob_clean();
    echo $whatever;
    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.

Further Reading - External Resources

Related References