Why the pagination for a query modified by pre_get_posts doesn’t mind the number & order of posts sorted & selected based on a custom date time field

I have the following task I try to accomplish. I want to display events in the post post type. I wanted to sort them by date and time and there should be events only displayed happening right now or in the future. Old posts shouldn’t be displayed in the front-end at all. Therefor I have attached a custom date time field event_start with Advanced Custom Fields 5.6.10 to the post type post. For the test purposes I have only seven posts, six upcoming and one passed with the following dates.

Post 0

Publish date: 28.06.2018

Event date: 05.07.2018 18:00

Post 1

Publish date: 30.05.2018

Event date: 06.08.2018 21:08

Post 2

Publish date: 29.05.2018

Event date: 06.08.2018 21:20

Post 3

Publish date: 14.07.2018

Event date: 10.08.2018 08:00

Post 4

Publish date: 23.07.2018

Event date: 12.08.2018 08:00

Post 5

Publish date: 24.07.2018

Event date: 23.08.2018 08:00

In the WordPress backend I’ve the number of shown posts to 4. The website is using the Phlox theme which is based on Elementor. For narrowing down the posts and satisfying the described constraints I’ve created a small plugin utilising pre_get_posts. The particular function created looks like that:

function mv_pre_get_posts( $query ) {

if ( class_exists( ‘ACF’ ) ) {
// Queries aren’t modified for the admin menu.
if ( is_admin() ) {
return $query;
}
// Queries are modified for the post type ‘post’ only.
if ( isset( $query->query_vars[‘post_type’] ) && ( ‘post’ === $query->query_vars[‘post_type’] || is_single() ) ) {
$query->set( ‘orderby’, ‘meta_value’ );
$query->set( ‘meta_key’, ‘dattime’ );
$query->set( ‘order’, ‘ASC’ );
$query->set( ‘posts_per_page’, get_option( ‘posts_per_page’ ) );
$query->set( ‘meta_query’, array(
‘relation’ => ‘AND’,
array(
‘key’ => ‘dattime’,
‘compare’ => ‘>=’,
‘value’ => date( ‘Y-m-d H:i:s’, strtotime( ‘-8 hours’ ) ),
‘type’ => ‘DATETIME’,
),
) );
}
return $query;
} else {
add_action( ‘admin_notices’, ‘mv_mvquery_notice’ );
}
}
add_action( ‘pre_get_posts’, ‘mv_pre_get_posts’ );

I’ve also setted the posts_per_page like recommendet in here How to fix pagination for custom loops? and used the get_option function to pull the set number automatically. If I take a look at the front-page now, Post 1 to Post 4 are displayed correctly on the first page. But now the issues with pagination are about to start. If I go to the second page again Post 1 to Post 4 are shown, instead of Page 5 only, which I would have expected.

If I click onto Page 4 to get into the single view Post 5 is correctly shown as next as well as Post 3 for previous. If I go on clicking the previous links further I get to Post 0, which shouldn’t show up at all, then Post 1 then Post 2.

If I start from Post 1 in single view, instead of only seeing the next Post 2 link I get Post 2 for previous and Post 0 for next. After clicking Post 0 next, Post 3, Post 4 and Post 5 follow up.

Is there a way to make the pagination adhere the settings for pre_get_post and minding the given query results for the front-page as well as for each single view with the correct sorting order and number of displayed posts?

Read more here:: Why the pagination for a query modified by pre_get_posts doesn’t mind the number & order of posts sorted & selected based on a custom date time field

Leave a Reply

Your email address will not be published. Required fields are marked *