0

On archive pages, I let WordPress handle the archive page and load the first 10 posts, then I load more posts with AJAX requests, and this AJAX request is returning weird results.

My query inside the AJAX handler looks like this:

$query_args = array(
    'post_type' => 'post',
    'posts_per_page' => get_option( 'posts_per_page' ), // 10 by default
    'offset' => get_option( 'posts_per_page' ), // 10 by default
    'cat' => 8 // the category ID
);
$wp_query_archive = new WP_Query( $query_args );

The problem: If the post count of the AJAX query is less than 10, i get one duplicate post.

If the posts were numbered, the first query (the default archive query that returns the first 10 posts in selected category) returns: 1,2,3,4,5,6,7,8,9,10, the second query made by AJAX request and described above returns: 10,11. Which then results in post duplication on front end.

However, if there is 10 or more post for the AJAX query, the query returns: 11,12,13,14,15,16,17,18,19,20

If there is only one post returned by the AJAX query, the query returns only that one post: 11, which is right, but when there are two posts to return, the query returns: 10,11,12.

When there's 5 posts for the AJAX query, the query returns the right posts too, meaning: 11,12,13,14,15

Is there some magic to WP_Query() that makes it behave this way?

Addition: I can't use paged query parameter, as Jacob Peattie pointed out, because I am using that query to load posts from multiple "pages" when the user hits page with hash containing string "#page3" for example.

  • Or better yet, don't use offset, just use 'paged' => 2, and don't bother with posts_per_page, since you're using the default anyway. – Jacob Peattie Apr 7 '18 at 14:14
  • If the offset starts at 0, how is it then that the query returns the right posts when there is more then 10 posts to load? I am using the same query every time. And as I said, if there is 1 post to load, it returns only that post 11, but if there are 2 posts to load, the query returns 10,11,12. – Vincurekf Apr 7 '18 at 14:34
1

Fixed it. After all it was really dumb error on my part. The WP_Query() does not filter out unpublished posts by default. The internal archive page query does filter these posts out.

I had to add 'post_status' => 'publish' to the $query_args array and everything is now working as expected.

The final query then looks like this:

$query_args = array(
    'post_status' => 'publish'
    'post_type' => 'post',
    'posts_per_page' => get_option( 'posts_per_page' ), // 10 by default
    'offset' => get_option( 'posts_per_page' ), // 10 by default
    'cat' => 8 // the category ID
);
  • Your final query example doesn't have the bit you said you added... – Jacob Peattie Apr 7 '18 at 14:51
  • I am quite distrait right now, thanks for noticing, fixed it. – Vincurekf Apr 7 '18 at 15:00
0

Just use the paged parameter to get the 2nd (or 3rd or 4th etc.) page:

$query_args = array(
    'post_type' => 'post',
    'paged'     => 2,
    'cat'       => 8
);
$wp_query_archive = new WP_Query( $query_args );

If you keep track of which page you're up to in JS then you can just pass that page number directly into paged to get the right posts.

PS: You were missing a > for the cat argument, and if you're getting the category by ID you should use an integer. I've corrected both of these in my example.

EDIT: If you need to handle multiple pages at once on initial load, based on the URL hash, then handle that with a different parameter in AJAX:

$query_args = array(
    'post_type' => 'post',
    'cat'       => 8
);

if ( isset( $_GET['pages'] ) ) {
    $query_args['posts_per_page'] = $_GET['pages'] * get_option( 'posts_per_page' );
} else if ( isset( $GET['page'] ) ) {
    $query_args['paged'] = $_GET['page'];
}

$wp_query_archive = new WP_Query( $query_args );

Then in your JS, if you want multiple pages at once send pages with the number of pages worth of posts that you want, but when loading more send page with the specific page number you are after.

  • I can't use that because I am also loading posts on load page if the page hash contains string "#pageX" where X is the page number, and in the ajax request I then set the posts per page to page * posts_per_page and send that to the AJAX query. Thanks for the warning, I've fixed my question. – Vincurekf Apr 7 '18 at 14:24
  • I don't see the problem. You can still do that for the initial query. Have your AJAX callback handle the initial load with posts_per_page, then additional loads just query the default posts per page with the paged parameter. – Jacob Peattie Apr 7 '18 at 14:28
  • I've fixed it. Boy was it dumb error. Apparently, WP_Query() does not filter out unpublished posts. SO I was getting one unpublished post in the AJAX query, but the internal archive page query filtered it out. Thank for your help anyway! – Vincurekf Apr 7 '18 at 14:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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