phpwordpresswordpress-theming

$wp_query and WP_QUERY - same arguments, different results


I spend this whole day trying to figure out a problem with a combination of a custom query and custom post types. This is my last resort...

The setting

I wrote a plugin that introduces some custom post types to my WordPress. To display them in the main query I hooked them into the query like this:

function add_cpt_to_query( $query ) {

    *some code...*

    // add custom post types to query
    if ( !( is_admin() || is_post_type_archive() || is_page() ) && $query->is_main_query() ) {
      $query->set('post_type', array_merge( array('post'), $cpt ) );
    }
}
add_action('pre_get_posts','add_cpt_to_query');

In my theme on the other hand I setup ajax pagination like this:

function setup_pagination() {

    global $wp_query;

    $max_pages  = $wp_query->max_num_pages;
    $current_page   = ( $wp_query->paged > 1 ) ? $wp_query->paged : 1;
    $ajaxurl    = admin_url( 'admin-ajax.php' );


    wp_register_script( 'ajax-pagination', get_template_directory_uri() .'/js/dummy.js', array('jquery'), '', true);

    wp_localize_script( 'ajax-pagination', 'ajaxpagination', array(
        'max_pages'     => $max_pages,
        'current_page'  => $current_page,
        'ajaxurl'       => $ajaxurl,
        'query_vars'    => $wp_query->query_vars
    ));

    wp_enqueue_script( 'ajax-pagination' );
}
add_action( 'wp_enqueue_scripts', 'setup_pagination' );

function pagination() {

    $query = $_POST['query_vars'];

    $query['paged'] = $_POST['next_page'];

    /*
    $query = array(
                'paged' => 2,
                'post_type' => array('post', 'custom_post_type_1', 'custom_post_type_2' )
            );
    */

    $posts = new WP_Query( $query );
    $GLOBALS['wp_query'] = $posts;

    // Start the loop.
    while ( have_posts() ) : the_post();
    ?>
    *some code...*
    <?php endwhile;

    die();

}
add_action( 'wp_ajax_nopriv_ajax_pagination', 'pagination' );
add_action( 'wp_ajax_ajax_pagination', 'pagination' );

and the script part:

$.ajax({
            url: ajaxpagination.ajaxurl,
            type: 'post',
            data: {
                action:         'ajax_pagination',
                query_vars:     ajaxpagination.query_vars,
                next_page:      parseInt(ajaxpagination.current_page) + 1
            }
        });

The problem

If I pass the query_vars array I get from $wp_query with the altered 'paged' value back to WP_QUERY, it returns the wrong set of posts. It looks like, that WP_QUERY does not account for the cpts in the loop. Though these cpts are mentioned in the 'post_type' of the query_vars array and thereby passed along to the new WP_QUERY.

When I manually set 'post_type' and only pass this argument, it works as intended. The aspect that blows my mind is, that the resulting query_vars used in the ajax call to WP_QUERY are exactly the same, but only when I manually set 'post_type' the pagination works as it should.

I dont know if this was a somewhat understandable explanation, but I'm thankful for every idea that could help me out. Big THX!


Solution

  • Ok... I got it now.

    I made a mistake in wp_localize_script(). The query_vars should be a json-string, I on the other hand just passed the array itself. My code above has to be altered in two lines:

    function mk_setup_pagination() {
    
        ...
    
        wp_localize_script( 'ajax-pagination', 'ajaxpagination', array(
            ...
            'query_vars'        => json_encode($wp_query->query_vars) <- convert to json-string
        ));
    
        ...
    }
    
    function mk_pagination() {
    
        $query = json_decode( stripslashes( $_POST['query_vars'] ) , true);  <- convert json-string to array
    
    ...
    

    Works like a charm now. :)

    btw: the code is based on a tutorial by wpmudev.org: Loading WordPress Posts Dynamically With AJAX