Exclude expired sticky posts

时间:2015-12-07 作者:Christopher

我使用下面的代码来排除过期的帖子,它工作正常,但不排除过期的粘性帖子。

//* 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);
    }
}

1 个回复
最合适的回答,由SO网友:Pieter Goosen 整理而成

编辑下面是我的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;
});

相关推荐