There are several guides available to implement ajax functionality in WordPress. When it comes to implementation in real-world, things get confusing pretty easily.
Ajax in WordPress is typically relied upon for communication between JavaScript & PHP (and vice versa). The data-type typically used for such communication is json. With that out of the way, how do you implement such communication to precise standards allowing data-validation and proper security authentication etc?
The official WordPress codex covers the basics of implementing ajax in admin area as well as front-end and also covers how to enqueue the script, pass it data by the way of localizing etc. For the basics please refer to the following articles:
Ajax in WordPress Developer Handbook
Where this gets tricky is when you want to use the proper functions on the server-side to respond to an ajax request. In all as of this date, there are 3 WordPress functions which allow you to send json data in response to an ajax request:
wp_send_json_success
wp_send_json_error
wp_send_json
wp_send_json_success
and wp_send_json_error
are the ones that should typically be used in favour of data validation. They are basically wrappers around the third function (wp_send_json
). wp_send_json_success
and wp_send_json_error
basically wrap the json data and include another Javascript property named success
the value of which is true
in case of wp_send_json_success
and false
in case of wp_send_json_failure
.
The catch is that oftentimes the value of the success
property is confused with an ajax response failure.
If you requested a json data-type and the data you received came along with the success
property, here’s what it means in the various following cases:
Ajax Success Handler
1. success
is true
:
The server was able to fulfill the request successfully: The ajax request got a valid json response and completed successfully.
{ "success": true, "data": { "property1": "value1" } }
2. success
is false
:
The server was NOT able to fulfill the request successfully ; the ajax request however got a valid json response and completed successfully.
{ "success": false, "data": { "property1": "value1" } }
3. The success
property doesn’t exist:
The ajax request-response completed successfully. Validate the data before handling it.
{ "property1": "value1" }
In this case the data could also be non-json and you should validate the data in either case.
All the above three cases trigger the JQuery success
handler becasue regardless of server having executed your requested successfully or unsuccessfully, the server did successfully respond with a response.
Ajax Error Handler
The jQuery “error” handler comes in when a response from the server was not received; probably timedout for some reason or the other. That’s where you’d need the UI to reflect a failure.
Ajax Complete Handler
The JQuery “complete” handler triggers after the “success” and / or “error” handlers have finished executing. Thus it triggers at the very end regardless of whether the ajax call was successful or not.
Singleton PHP Class Demonstrating Ajax in WordPress Admin Area
The following singleton class in PHP can be used to experiment with various kinds of requests and responses inside the WordPress Admin area. You can deploy it as a drop-in, a must-use plugin or modify / add it to your plugin / theme. It’s well-commented (but untested).
<?php // Singleton class class Ajax_in_WP { static function get_instance() { static $instance = null; if ( is_null( $instance ) ) { $instance = new self(); $instance->init(); } return $instance; } // Hook relevant functions function init() { add_action( 'admin_footer', array( $this, 'footer_script' ) ); add_action( 'wp_ajax_my_ajax_handler', array( $this, 'my_ajax_callback' ) ); // Respond to logged-in users. add_action( 'wp_ajax_nopriv_my_ajax_handler', '__return_false' ); // // Do not respond to logged-out users. } // Server-side ajax request handler / responder function my_ajax_callback() { check_ajax_referer( 'my_ajax', 'my_ajax_nonce' ); // don't respond if nonce is not valid // Uncomment either of the following lines. Only the first wp_send_json* call will be executed; subsequent lines will not be executed since wp_send_json* functions call wp_die / die wp_send_json_success( 'Uncommenting this line will return a json object with the success property set to true.' ); wp_send_json_error( 'Uncommenting this line will return a json object with the success property set to false.' ); wp_send_json( 'Uncommenting this line will return a json object without the success property.' ); wp_send_json( $_REQUEST ); // Want to see what data was sent by the browser and received by the server? } // Browser-side script that triggers ajax request and handles response / error etc. function footer_script() { ?> <script type="text/javascript"> // Trigger as soon as page is loaded jQuery(document).ready(function($){ // Set up what data we are going to send to the server. let my_ajax_request = { my_ajax_nonce: '<?php echo wp_create_nonce( 'my_ajax' ); ?>', action: "my_ajax_handler", user: { fn: $('#my_user_fname').val(), ln: $('#my_user_lname').val(), email: $('#my_user_email').val(), } }; $.ajax({ url: ajaxurl, method: 'POST', data: my_ajax_request, // Triggered when the ajax response is received (response data is not validated yet) success:function(response_data,textStatus,jqXHR){ console.log('==== SUCCESS HANDLER STARTS ===='); if ((typeof response_data) === 'object') { // Verify that the data is a json object if (response_data.hasOwnProperty('success') ) { // ajax request has a success but we haven't tested if success is true or false if( response_data.success ){ // If the value of success property is true. Triggered by wp_send_json_success console.log('Server fulfilled your request successfully'); } else { // // If the value of success property is false. Triggered by wp_send_json_error console.log('Response received from server that it failed to fulfill your request'); } } else { // Triggered by wp_send_json (success property does not exist) console.log('Response received from server. Validate the response before handling it'); } } else { // Triggered when the data type is not json console.log('Response received is not json but some other data type probably text.'); } console.log('response_data'); console.dir(response_data); console.log('textStatus'); console.dir(textStatus); console.log('jqXHR'); console.dir(jqXHR); console.log('==== SUCCESS HANDLER ENDS ===='); }, // Triggered when the ajax response failed error:function(jqXHR,textStatus,errorThrown){ console.log('==== ERROR HANDLER STARTS ===='); console.log('Ajax request could not be completed. Perhaps network issue or server did not respond etc.'); console.log('jqXHR'); console.dir(jqXHR); console.log('textStatus'); console.dir(textStatus); console.log('errorThrown'); console.dir(errorThrown); console.log('==== ERROR HANDLER ENDS ===='); }, // Always runs regardless of success and failure complete:function(jqXHR,textStatus){ console.log('==== COMPLETE HANDLER STARTS ===='); console.log('Ajax complete always gets called regardless of success or error. Use it if you want to do something anyway.'); console.log('jqXHR'); console.dir(jqXHR); console.log('textStatus'); console.dir(textStatus); console.log('==== COMPLETE HANDLER ENDS ===='); }, }); // Ajax }); // document-ready </script> <?php } } // class Ajax_in_WP function Ajax_in_WP() { return Ajax_in_WP::get_instance(); } Ajax_in_WP();
Assuming that you are a developer implementing ajax in WordPress, you can tell that the above script responds inside the browser’s javascript console.
Feel free to drop a line if required.