DEV Community

Martin
Martin

Posted on

Best practices on responding to AJAX calls in Wordpress Plugins

Preface (you can skip it, if you want): A customer came up to me with a request to build an application and combine it with an existing Wordpress installation. At the beginning I was hesitant, but I found, that using "Wordpress as a Backend" has quite a few advantages: It has baked-in user roles and capabilites and you can use already existing plugins to simplify your own development.

Task

As I mentioned in the preface, using Wordpress as a backend comes with a few benefits, I decided to program the new application as a plugin. But I neither wanted to use the (sometimes weird) combination of PHP and HTML nor send all the needed data via forms to the backend.

I wanted to stick with tools I was more familiar with:

  • I choose Vue.js as my frontend for the application.
  • And the backend would be a Wordpress plugin.

When developing with a frontend framework like Vue.js, you have to use AJAX calls for communication with your backend. And that's when I found out, that the existing documentation on AJAX with Wordpress feels quite old (https://codex.wordpress.org/AJAX_in_Plugins) and there are no complete code examples and no best practices on how to work with AJAX calls when using Wordpress.

Content

In this article I will not only cover "AJAX with Wordpress", but also a few related topics:

  • Wordpress AJAX basics
  • Responding to AJAX calls from your Wordpress plugin
  • Authorization
  • Frontend best-practices
  • Ship your frontend together with your plugin
  • Nonces

Wordpress AJAX basics

Please turn on debugging (https://wordpress.org/support/article/debugging-in-wordpress/) by using both WP_DEBUG and WP_DEBUG_LOG, it will make your life easier :)

This wordpress article explains the basics of responding to ajax calls.

Here is a Gist which also describes everything you should know:

One thing to remark: You always have to check for permissions in your AJAX calls

Responding to AJAX calls

Within your functions it is highly recommended to use wp_send_json_success or wp_send_json_error functions to send data back to the client (here is a informative stackexchange post on that)

On default settings, the client has to send all data as x-www-form-url, otherwise you cannot access it with $_POST['something']. I did not like that and found a way to send parse the data when using application/json Content-Type:

$data = json_decode(file_get_contents('php://input'));
Enter fullscreen mode Exit fullscreen mode

Now your $data variable contains all the request data. You could now use object destructuring to access the data more easily (but it depends on your PHP version). Skip to the Frontend Best practices section when you are curious on how to send data from the frontend to the AJAX handler

Authorization

As explained in the first section, you have to do the authorization for your AJAX functions/routes yourself. It really depends on the application and use case of your plugin. You can try to use Wordpress built-in current_user_can function, or build your own permissions/role system, which I had to do. In the end, I ended up with following code:

$data = json_decode(file_get_contents('php://input'));
$id = $data->locationId;
// I check whether the current user is allowed to access the given location
// If not the function returns wp_send_json_error(null, 401)
checkUserAccessToLocation($id);
Enter fullscreen mode Exit fullscreen mode

Frontend Best Practices

You should have a single component in your frontend project which handles the calls to the backend: It is easier to maintain and reduces the probability of errors. I am using Vue.js and have a simple class for handling the communication with the backend (I am using axios)

export class BackendCommunicationService {

    private static async buildCall(data: {[k: string]: any}) {
        const params = new URLSearchParams()
        params.append('action',data['action'])
        delete data['action']
        const res = await Vue.axios.post('/wp-admin/admin-ajax.php', data, {params})
        return res.data
    }
// ..... other functions
}
Enter fullscreen mode Exit fullscreen mode

Using the buildCall function within the class is easy: this.buildCall({action: 'insert_name', name: 'Foobar'}). This will call your (hopefully previously) defined wp_ajax_insert_name ajax action.

Shipping your plugin

I wanted to ship the plugin with the full application code. So I build the frontend project and copy the generated dist folder into an assets folder of the plugin. Here is my bash script:

cd frontend && npm run build
cp -r dist/* ../plugin/assets/
Enter fullscreen mode Exit fullscreen mode

In order to have predictable file names, I have to add filenameHashing: false to my vue.config.js.

Now I have my frontend code in the assets folder. How do I include the plugin with the whole application into wordpress? The easiest way I found is by using a shortcode. This is my PHP code to ship my application through a shortcode:

<?php
add_shortcode('get_ll_include_tags','get_ll_include_tags_func');

function get_ll_include_tags_func() {
    // Load JS files
    wp_register_script( 'vue-app.js', plugin_dir_url( __FILE__ ) . 'assets/js/app.js');
    wp_enqueue_script( 'vue-app.js' );
    wp_register_script( 'vue-vendors.js', plugin_dir_url( __FILE__ ) . 'assets/js/chunk-vendors.js');
    wp_enqueue_script( 'vue-vendors.js' );

    // Load CSS files of application
    wp_register_style( 'vue-app.css', plugin_dir_url( __FILE__ ) . 'assets/css/app.css');
    wp_enqueue_style( 'vue-app.css' );
    wp_register_style( 'vue-vendors.css', plugin_dir_url( __FILE__ ) . 'assets/css/chunk-vendors.css');
    wp_enqueue_style( 'vue-vendors.css' );


    ob_start();
    ?>
        <div id="app">
            <div class="app__loading-spinner"></div>Application is loading...
        </div>
    <?php
    return ob_get_clean();
}
?>
Enter fullscreen mode Exit fullscreen mode

Now I can use [get_ll_include_tags] in any wordpress page and my application will be loaded.

Nonces

To be honest, this is a topic I am still indecisive about. Nonces are there for a good reason, but as all AJAX calls are POST requests and I am checking the authorization for every call, I am not sure whether nonces are needed? But please correct me, if I am wrong! If nonces are needed, I already have a few ideas on how to implement them.

The End

I hope this helps some people, I wish I had had such a post when starting with PHP Wordpress plugin development.

Disclaimer: I am new to Wordpress plugin development and PHP, so please comment if you find an error or have a remark on something:)

Top comments (1)

Collapse
 
rainocode profile image
rainocode

AJAX (Asynchronous JavaScript and XML) calls play a crucial role in enhancing user experience and interactivity in WordPress plugins. However, handling AJAX requests properly is essential for maintaining security, performance, and compatibility with WordPress standards. Here are some best practices for responding to AJAX calls in WordPress plugins:
rainocode.com/blog/best-practices-...