1

I've created a custom post type called 'award':

function award_post_type() {

    $labels = array(
        'name' => 'Awards',
        'singular_name' => 'Award'
    );
    $args = array(
        'labels' => $labels, 
        'public' => true,
        'has_archive' => true,
        'supports' => array( 'title', 'editor', 'excerpt' )
    );
    register_post_type( 'award', $args );

}

add_action( 'init', 'award_post_type' );

Now I am in the award post type's page archive, and I'm trying to display a list of awards ordered by the awards' deadlines (which are stored in a custom field). Next posts should be loaded via AJAX at the click of a 'Load More' button.

First thing I did was alter the main query using pre_get_posts:

function order_by_deadline( $query ) {
    if ( ! is_admin() && is_post_type_archive( 'award' ) ) {
        if( $query->is_main_query() ) {
            $query->set( 'orderby', 'deadline' );
            $query->set( 'meta_key', 'deadline' );
        }
    }
}

add_action( 'pre_get_posts', 'order_by_deadline' );

This works okay. But when I try to load the next posts using AJAX, no results are shown. Here's the action I pass to the AJAX call, which includes the custom WP_Query I've created to call the new posts:

function load_next_awards() { 

    // The number of the page is received from an attribute of the Load More button. I'm 100% sure this has nothing to do with the issues I'm having, so just ignore it.
    $page = $_POST[ 'page' ]; 

    $args = array(
        'paged' => $page, 
        'post_type' => 'award',
        'post_status' => 'publish'
        'post__not_in' => get_option( 'sticky_posts' ),
        'orderby' => 'meta_value_num',
        'meta_key' => 'deadline'
    );

    $next_posts = new WP_Query( $args );  

    if( $next_posts->have_posts() ) :   
        while( $next_posts->have_posts() ) : the_post(); 
            get_template_part( 'views/post/content', get_post_format() );
        endwhile;
    endif;

    wp_reset_postdata();

    die();

} 

I'm at a loss of ideas. The custom WP_Query looks correct to me, but it returns no results when I click on 'Load More'. If I change the post_typeparameter to post or page instead, it does correctly show my posts and pages.

6
  • before really answering, can you test the same loop but without the get_template_part. Instead, using something like echo $post->post_title; ? Commented Nov 15, 2017 at 15:35
  • Look at the contents of $next_posts after the query is run, specifically $next_posts->request, you'll see exactly what is being queried.
    – Milo
    Commented Nov 15, 2017 at 16:44
  • @Milo I already did, and I can see that the query is empty, that's the problem. It's empty if I request my custom 'award' post types, but it's fine if I request Wordpress' default 'post' or 'page'.
    – grazdev
    Commented Nov 15, 2017 at 17:15
  • If you try var_dump($next_posts) it’s completely empty? Not the posts array, the actual SQL query in request is empty?
    – Milo
    Commented Nov 15, 2017 at 23:18
  • No, the SQL query is fine, it just returns no results. Here it is: "SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts WHERE 1=1 AND wp_posts.post_type = 'cal' AND ((wp_posts.post_status = 'publish')) ORDER BY wp_posts.post_date DESC LIMIT 8, 8"
    – grazdev
    Commented Nov 16, 2017 at 8:01

3 Answers 3

3

I've found the solution. The problem was I had a different number set for the posts_per_page parameter in the initial query and in the custom query I make via AJAX. In the code I provided posts_per_page is not even there because I'm using a few nested classes, so I've posted a stripped-down version of the code for simplicity. I was sure the issues was with custom post types, never thought using different posts_per_page could cause a problem. Apologies about that.

So yeah, if you're running into the same problem make sure that your posts_per_page is the same for all your queries!

1
  • You just saved me from hours of painful debugging. Thank you!
    – Wold
    Commented Mar 28, 2018 at 15:06
0

Try initializing the post with $next_posts->the_post() instead of just the_post(). the_post by itself will try to use the main query and in this context there isn't one.

1
  • Thank you, but it didn't help.
    – grazdev
    Commented Nov 15, 2017 at 16:23
0

If you are using AJAX, you gotta control your output to "spit" the context only once. And whenever you use a template part or any other functions that print content, it will probably output several times (either by using echo, _e or even HTML markup).

In cases like this you must use the output buffer. Basically, you will put all your content in this buffer instead of printing it and after all processing, you finally outputs/prints it.

Here you can find good reference of using it and [here the PHP manual page] about it 2.

Your functions would be something like this:

function load_next_awards() { 

    // The number of the page is received from an attribute of the Load More button. I'm 100% sure this has nothing to do with the issues I'm having, so just ignore it.
    $page = $_POST[ 'page' ]; 

    $args = array(
        'paged' => $page, 
        'post_type' => array( 'award' ),
        'post_status' => 'publish'
        'post__not_in' => get_option( 'sticky_posts' ),
        'orderby' => 'meta_value_num',
        'meta_key' => 'deadline'
    );

    $next_posts = new WP_Query( $args );  

    if( $next_posts->have_posts() ) :   
        //initiates output buffer
        ob_start();
        while( $next_posts->have_posts() ) : $next_posts->the_post(); 
            get_template_part( 'views/post/content', get_post_format() );
        endwhile;

        // clean outbut buffer (ob) after assigning it's contents to a variable
        $html = ob_get_clean();
    endif;

    wp_reset_postdata();

    // echo cached html markup and leave function
    echo $html;

    die();

} 

Let me know if it helps.

4
  • Just tried, but I get a 500 error. Plus, like I said in my question the AJAX call works if I change the post_type from 'award' to 'post' or 'page', so I guess there must be something wrong with the WP_Query, not with AJAX.
    – grazdev
    Commented Nov 15, 2017 at 16:22
  • before going any further, please 1) test what I asked on my comment above : " test the same loop but without the get_template_part. Instead, using something like echo $post->post_title; ?" so we can check if the query is working 2) can you share your template part code? Commented Nov 15, 2017 at 17:03
  • I know the query for 'award' post types is NOT working because I have var_dumped it and it returns no results. Differently, it does work and it does return results if I set 'post' or 'page' as the post_type. Anyway, echoing $post->post_title doesn't work. As to the template part code, it includes a few classes (OOP) so it would be confusing to share it, but even if I take everything away and just echo a <p>Hello</p>, no new posts show up.
    – grazdev
    Commented Nov 15, 2017 at 18:21
  • Just covering all bases: 1) How was the award post type created? 2) as pointed by Welcher, did you changed to $next_posts->the_post() ? Commented Nov 15, 2017 at 22:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.