Fetching more posts in WordPress via AJAX

What’s the best way to fetch the next page in post archives and other lists like search results?

This question has been asked many times already, but the answers not good enough for me.
So far, I’ve found two ways of doing it.

Read More
  1. Using an AJAX request to the standard URL (like example.com/category/mycat/page/2). This is done using the $.load function of JQuery which strips the result leaving only the contents of some block with the specified id. I believe this is inefficient both for the client (because unnecessary content is loaded and processed) and for the server (because such a request processes menus, widgets, etc., that are not needed).

  2. With a custom ajax handler using the add_action function. The big problem with this option is that the handler is not universal! It circumvents the normal query parsing, creating a custom WP_Query object instead. Clearly, this is not the way.

I am considering the following:

  1. Register a query variable that would make the template display the page in JSON format and make a request like so: example.com/category/mycat/page/2?showjson=true. In the theme check for this variable and adjust output accordingly.

  2. Get query_vars and using wp_localize_script pass them to the script. Then make the AJAX call with these variables and handle them appropriately. (Basically, this would be a beefed-up version of option 2 above).

Then maybe there is some other way of doing this?

ADDED: Making a custom handler could be potentially used to improve performance, as not all of WordPress needs to be loaded.

Related posts

1 comment

  1. I ended up modifying the archive.php file to serve different content when requested normally and via ajax.

    if ((isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest')) {
        $response = array();
        $response['posts'] = '';
        if (have_posts()) {
            ob_start();
            while (have_posts()) {
                the_post();
                get_template_part('content');
            }
            $response['posts'] .= ob_get_clean();
        } else {
            //no posts
            $response['posts'] .= 'nothing';
        }
        echo json_encode($response);
    } else {    
        //normal template code here
    }
    

    After that, getting items via JS is easy:

    $.ajax ({
        type: "GET",
        url: more_ajax_url,
        data: {},
        dataType: 'json',
        success: function (result) {
            $('#archive_container').append(result.items);
        }
    });
    

    There is also some code to pass the link to the next page, but that should not be hard to implement.

    The advantage of this method is that the request is fully processed by wordpress and all its filters and actions. And it is much better than the $.load, because no unnecessary data is passed from the server.

Comments are closed.