To access server-side functions you’ll need to trigger a server event from JS using AJAX, JSON API, XML/RPC, custom endpoints, or even template_redirect hooks. Just be sure to liberally sprinkle nonces when performing major functions.
The simple and proven technique is the AJAX call. Setup a couple handlers when AJAX receives an action
while the user is either logged-in or out (nopriv).
add_action( 'wp_ajax_add_foobar', 'prefix_ajax_add_foobar' );
add_action( 'wp_ajax_nopriv_add_foobar', 'prefix_ajax_add_foobar' );
function prefix_ajax_add_foobar() {
// Handle request then generate response using WP_Ajax_Response
}
Then trigger the action via JS. The response is whatever you output in the handler but usually wp_send_json_success will work fine.
jQuery.post(
ajaxurl,
{
'action': 'add_foobar',
'data': 'foobarid'
},
function(response){
alert('The server responded: ' + response);
}
);
If the JS needs access to server variables at runtime consider using wp_localize_script for more than text translations. It’s really your opportunity to pass inline JS before a script loads. Thus ensuring JS has access to proper URLS, settings and states required for your app. ajaxurl
may exist for some people but localizing that onto a variable will assure you that it’s the correct url.
// Register the script
wp_register_script( 'some_handle', 'path/to/myscript.js' );
// Localize the script with new data
$translation_array = array(
'some_string' => __( 'Some string to translate', 'plugin-domain' ),
'a_value' => '10'
);
wp_localize_script( 'some_handle', 'object_name', $translation_array );
// Enqueued script with localized data.
wp_enqueue_script( 'some_handle' );
The JSON API is also a good choice and very easy to setup. The major drawback is that it’s only a few weeks old in core (since 4.4) and not fully established (full by 4.5). If you don’t mind living on the edge you can be up and running in a short time with custom endpoints.
function my_awesome_func( $data ) {
$posts = get_posts( array(
'author' => $data['id'],
) );
if ( empty( $posts ) ) {
return null;
}
return $posts[0]->post_title;
}
add_action( 'rest_api_init', function () {
register_rest_route( 'myplugin/v1', '/author/(?P<id>\d+)', array(
'methods' => 'GET',
'callback' => 'my_awesome_func',
) );
} );
XML RPC was cool enough that everyone is switching to the JSON API if they can help it. It’s a proven solution but who wants XML these days?
add_filter('xmlrpc_methods', function ($methods) {
$methods['myNamespace.getTotalImageCount'] = 'rpc_myNamespace_getTotalImageCount';
return $methods;
});
function rpc_myNamespace_getTotalImageCount($args)
{
return array_sum((array)wp_count_attachments('image'));
}
add_action('parse_request', function () {
// PULL USER CREDS FROM CURRENT USER
global $current_user;
$user = $current_user->user_login;
$password = $user->data->user_pass;
include_once(ABSPATH . WPINC . '/class-IXR.php');
include_once(ABSPATH . WPINC . '/class-wp-http-ixr-client.php');
$xmlrpc_url = home_url('xmlrpc.php');
$client = new WP_HTTP_IXR_CLIENT($xmlrpc_url);
// CALL OUR CUSTOM METHOD
$response = $client->query('myNamespace.getTotalImageCount', array(0, $user, $password));
echo 'Response:<pre>';
$count = $client->message->params[0];
print_r("{$count} total images");
echo '</pre>';
wp_die('FIN');
});
If you’re curious about how much AJAX you should use then look no further than the future of WordPress.com’s pet project Calypso where they redefine the admin back-end using as much JS as possible.
All these options are great unless someone turns off JS so keep that in mind when you construct your site.
There are also a few tools to help out along the way.
Postman – REST Client extension for Chrome can test GET and POST requests – DEMO.
Monkeyman Rewrite Analyzer WP plugin can double check your custom rewrite endpoints are working correctly.