编辑下面是我的ORIGINAL ANSWER. 而不需要更改主查询和$posts
global要删除过期的粘性,为什么不将帖子完全从粘性中删除,即取消已过期帖子的粘性。这样,我们就不需要检查过期的胶粘物并在每次页面加载时删除它们。
我们要做的是运行scheduled event 每天(或每天两次,任何最适合你的都可以),它将查找过期的胶粘物,并将其从粘性帖子阵列中移除。
NOTE:, 在运行此代码之前,请确保要从保存在db中的数组中删除粘滞。运行此功能后,将无法在中使用任何现有帖子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;
});