In Custom page – next_posts_link Not working while previous_posts_link is working

You have a few issues here

  • The use of 'no_found_rows' => true is incorrect. no_found_rows is meant for queries that will not be paginated. 'no_found_rows' => true is passed by get_posts to WP_Query to legally “break” pagination, that is why get_posts cannot be paginated as normal.

    What is really happening here is, by default is, when you query the db for posts with WP_Query, WP_Query runs through the whole db and look for all posts matching the query parameters. This happens with the main query and custom queries. So, if you need 5 posts per page, your query will return 5 posts, but the complete db was checked for all posts matching the query and that amount is returned and stored into the $found_posts property of the query object. The amount of posts found matching the query is used to calculate (internally) the $max_num_pages property which is integral in calculating pagination in paginated queries. $max_num_pages is what will tell the pagination function how many pages of posts there will be (you can check the amount of pages there will be in your query with echo $printposts->max_num_pages) and then display the links accordingly.

    With no_found_rows set to true, the above process is skipped. WP_Query will now just look for the first 5 posts that matches the query, halt/stop execution and returns the 5 posts. The process of counting all posts in the db to establish all posts matching the specific query is skipped. So, as I said, you are now legally breaking pagination as pagination will not work on such a query. This is done to save on resources when a non paginated query is run. It make such a query faster and save on the amount of time that the query spends (unnecessary) in the db.

    As you need to paginate your query, you need to remove 'no_found_rows' => true

  • The next_posts_link() function is set to the amount of pages according to the main query object. On page templates, there wil only be one page ever, so your links will never work just on default. To make this work, you need to set next_posts_link() to the $max_num_pages property of your custom query. This is real easy, as the second parameter of next_posts_link() accepts a custom set of amount of pages. So all you need to do is to pass $printposts->max_num_pages as second parameter like this

    <div class="nav-next "><?php next_posts_link( 'Older posts ยป', $printposts->max_num_pages ); ?></div>
    

Just one extra note, suppress_filters are by default set to false which means that the posts_* filters can influence and modify the query as needed. I usually set this parameter to true for custom queries, then I know I am save and no custom filters can interfere with my custom query