2

I'd like to restrict the number of posts that show on my home page to 3, but have all the other archive, category, pagination pages, etc. at whatever number I set in the "reading" settings in the Wordpress dashboard.

Is there a nice way to do this in functions.php?

I tried the following, which does limit the posts on the home page to 3, but it also creates pagination links to pages with 3 posts each.

    add_action( 'pre_get_posts',  'change_posts_number_home_page'  );
function change_posts_number_home_page( $query ) {

if ($query->is_home() && $query->is_main_query() ) {
        $query->set( 'posts_per_page', 3 );

return $query;
}

Thanks in advance!

  • You specifically want to limit the number on the very first page, but not subsequent pages? That's going to be a lot harder to do than it sounds. The solution to this could be quite complex, it's a non-trivial problem that will require some heavy duty expertise – Tom J Nowell Aug 1 at 11:01
  • Hi Tom, thanks! I didn't realize this would be so difficult. Maybe a better solution would be to have a static page showing the three posts that I want to feature, and then disabling the pagination links below. What I'm trying to avoid is having WP generate tons of archive pages with just 3 posts each on them. I'd like 10-15 posts on every archive page, but only 3 posts on the home page. Not sure the best way to do this. I'm using the Astra (pro) theme, fwiw, and I'm pretty sure this question is beyond what I can ask them about supportwise. – Lori L Aug 2 at 11:36
1

So this is a tiny bit hacky, but it achieves want you want relatively cleanly without you needing to change your themes, which was presumably the point of wanting to do it in functions.php.

First make WP_Query think it's getting all the posts with default pagination settings as usual:

function change_posts_number_home_page( $query ) {
    if ($query->is_home() && $query->is_main_query() ) {
        $query->set( 'posts_per_page', -1 );
    }
}

add_action( 'pre_get_posts',  'change_posts_number_home_page'  );

Now add an SQL LIMIT so that WP_Query only receives 3 posts, but thinks it's asked for all of them, and so will a) not render pagination assuming your page length is 3 or more b) will only get three posts:

function set_wpquery_limit($limits, $wpq) {
    if ($wpq->is_home() && $wpq->is_main_query() ) {
        return "LIMIT 3";
    }
}

add_filter('post_limits', 'set_wpquery_limit', 10, 2);

Notes:

  • If a better answer turns up that allows you to turn off pagination with some more clean setting, that would be the way to go as this fools with WP_Query internals so is not ideal.
  • To me doing this in the 'presentation layer' i.e. the theme seems clearer and cleaner, but I can see that there's pletny of time you wouldn't want to do that, e.g. if creating a child theme was a ton of work just to tweak this.
  • This approach tested and working and didn't cause any problems on a clean WP with twentytwenty theme, however please test thoroughly in your situation.
  • Your original code has a } missing after the if
  • Your original code was an action hook. Actions don't look at return values, so you don't need a return there.
| improve this answer | |
  • Thanks, Mozboz. I do have a staging site I can test this on. My coding knowledge is limited to ... basically zilch. If I have something basic I can usually figure out what I need to change to get the number of posts I want, or the category, whatever. But all the other stuff is totally over my head. In any case, thanks for the help! – Lori L Aug 2 at 11:41
  • 1
    Cool, good luck, you should be able to post the stuff from my answer into functions.php and it'll either work or it won't. Just be a little careful as if your functions.php breaks you may lose access to the Wordpress admin, so make sure you have a way to restore it or edit it other than through the WP admin UI itself – mozboz Aug 2 at 12:23

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.