Исключить истекшие липкие сообщения

Я использую следующий код, чтобы исключить истекшие сообщения, и он отлично работает, но не исключает истекшие липкие сообщения.

//* Exclude expired posts add_action( 'pre_get_posts', 'exclude_expired_posts' ); function exclude_expired_posts( $query ) { if ( !is_admin() && $query->is_main_query() && !is_search() && !is_singular() && !is_date() ) { $meta_query = array ( 'relation' => 'OR', array( 'key' =>'ed_expiry', 'compare' => 'NOT EXISTS' ), array( 'key' => 'ed_expiry', 'value' => current_time( 'mysql' ), 'type' => 'DATETIME', 'compare' => '>', ), ); $query->set('meta_query', $meta_query); } } 

РЕДАКТИРОВАТЬ

Вот еще один подход к тому, который был в моем ОРИГИНАЛЬНОМ ОТВЕТЕ . Вместо необходимости изменять основной запрос и $posts global, чтобы удалить истекшие листы, почему бы не удалить записи полностью из-за того, что они липкие, т. Е. Разблокировать сообщения, срок действия которых истек. Таким образом, нам не нужно проверять истекшие листки и удалять их при каждой загрузке страницы.

Мы будем делать ежедневное запланированное мероприятие ( или два раза в день, что вам больше подходит ), которые будут искать устаревшие листки и удалить их из массива липких сообщений.

ПРИМЕЧАНИЕ. Перед запуском этого кода убедитесь, что вы хотите удалить листы из массива, сохраненного в db. Когда эта функция будет запущена, любой exired пост больше не будет доступен в get_option( 'sticky_posts' ) ).

 // Set our hook and function to remove sticky posts add_action( 'unstick_expired_posts', function () { // Get the sticky posts array $stickies = get_option( 'sticky_posts' ); // return if we do not have stickies if ( !$stickies ) return; // Get all expired stickies, just the id's $args = [ 'posts_per_page' => count( $stickies ), 'post__in' => $stickies, 'fields' => 'ids', 'meta_query' => [ // Taken unchanged from OP 'relation' => 'OR', [ 'key' =>'ed_expiry', 'compare' => 'NOT EXISTS' ], [ 'key' => 'ed_expiry', 'value' => current_time( 'mysql' ), 'type' => 'DATETIME', 'compare' => '>', ] ], // Add any additional arguments to get stickies by ]; // We will use get_posts because it already exclude sticky posts and skips pagination $expired_stickies = get_posts( $args ); // Check if we have posts, if not, return if ( !$expired_stickies ) return; /** * We will now compare the $q and $stickies array. We will use array_diff() * to return all stickies that does not appear in $q */ $active_stickies = array_diff( $stickies, $expired_stickies ); // We will now update the sticky posts option in db with $active_stickies update_option( 'sticky_posts', $active_stickies ); } 

Теперь мы можем планировать запуск этого мероприятия ежедневно, поэтому один раз в день мы будем проверять, есть ли какие-либо просроченные липкие сообщения, а если есть, мы удалим их из опции липких сообщений.

 // Add function to register event to wp add_action( 'wp', 'register_daily_expired_sticky_post_delete_event'); function register_daily_expired_sticky_post_delete_event() { // Make sure this event hasn't been scheduled if( !wp_next_scheduled( 'expired_post_delete' ) ) { // Schedule the event wp_schedule_event( time(), 'daily', 'unstick_expired_posts' ); } } 

Как я уже сказал, вы можете установить, чтобы событие запускалось чаще или реже, меняя daily к вашим потребностям.

Если вам действительно нужно удалить эти листы, вы можете включить функцию, которая будет выполняться внутри вашего действия pre_get_posts внутри условного тега is_home()

ОРИГИНАЛЬНЫЙ ОТВЕТ

Важные сообщения, IMHO, иногда просто боль в прикладе, когда вы начинаете показывать сообщения в соответствии с условиями, и это так в этой ситуации. Лучше всего было бы удалить липкие сообщения из основного запроса, а затем добавить их обратно в свойство $posts основного объекта запроса через фильтр the_posts

Во-первых, удалите липкие сообщения полностью из основного запроса с помощью нашего действия pre_get_posts

 add_action( 'pre_get_posts', function ( $q ) { if ( !is_admin() // Target only the front end && $q->is_main_query() // Targets only the main query && !$q->is_search() && !$q->is_singular() && !$q->is_date() ) { $meta_query = [['Your meta query conditions']], $q->set( 'meta_query', $meta_query ); $q->set( 'ignore_sticky_posts', 1 ); // Remove sticky posts $q->set( 'post__not_in', get_option( 'sticky_posts' ) ); // Remove stickies from the loop to avois duplicates } }); 

Вы не увидите никаких липких сообщений. Просто помните, я только что дал вам позвоночник, вы должны добавить весь свой другой код в мой или добавить мой к себе 😉

Теперь нам нужно добавить листы назад, но мы сделаем это через фильтр the_posts

 add_filter( 'the_posts', function ( $posts, $q ) { if ( !is_admin() // Target only the front end && $q->is_main_query() // Targets only the main query && !$q->is_home() // only add stickies on the homepage && !$q->is_paged() // Only target the first paged page ) { // Do this only if we have stickies to avoid all posts returned regadless // Get the array sticky posts (ids) from the db $sticky_array = get_option( 'sticky_posts' ); if ( $sticky_array ) { // Query our sticky posts according to condition $args = [ 'posts_per_page' => -1, // Query all stickies 'ignore_sticky posts' => 1, // Strange but true, exclude stickies 'post__in' => $sticky_array, // Query all posts from the $sticky_array 'meta_query' => [[]], // Add your meta query conditions as in OP // Add any other conditions as you need them ]; $sticky_posts = new WP_Query( $args ); // Now we will add our sticky posts in front of the our other posts $posts = array_merge( $sticky_posts->posts, $posts ); } } return $posts; });