我可以使用pre_get_posts函数通过元键排除帖子吗?


24

我看到许多人更喜欢使用pre_get_posts钩子代替query_posts。下面的代码可以正常工作,并显示所有具有“功能”元键的帖子

function show_featured_posts ( $query ) {
    if ( $query->is_main_query() ) {
       $query->set( 'meta_key', 'featured' );
       $query->set( 'meta_value', 'yes' );
    }
}

add_action( 'pre_get_posts', 'show_featured_posts' );

但是我希望将具有' featured'meta_key 的帖子从主要查询中排除。有一个简单的方法吗?

Answers:


33

我看到许多人更喜欢使用pre_get_posts挂钩而不是query_posts

好极了!

所以pre_get_posts过滤器WP_Query的对象,这意味着什么,你可以通过做query_posts()你可以通过做$query->set()$query->get()。特别是,我们可以利用该meta_query属性(请参阅Codex):

$meta_query = array(
                 array(
                    'key'=>'featured',
                    'value'=>'yes',
                    'compare'=>'!=',
                 ),
);
$query->set('meta_query',$meta_query);

但是..它将替换原始的“元查询”(如果有的话)。因此,除非您想完全替换原始的元查询,否则我建议:

//Get original meta query
$meta_query = $query->get('meta_query');

//Add our meta query to the original meta queries
$meta_query[] = array(
                    'key'=>'featured',
                    'value'=>'yes',
                    'compare'=>'!=',
                );
$query->set('meta_query',$meta_query);

这样,我们将元查询与现有元查询一起添加。

您可能/可能不希望将relation属性设置$meta_queryANDOR(返回满足所有或至少一个元查询的帖子)。

* 注意:此类查询将返回带有“功能”元关键字的帖子,但其值不是yes。它不会包括“功能”元键不存在的帖子。您将可以在3.5中做到这一点


因此,没有办法检查帖子的met​​a_key是否存在/是否为空?我将不得不等待3.5。然后。感谢您的回复。
卡莱尔2012年

我将简单地使用YesNo选项创建一个meta框,默认情况下将选择“否”。当我要发表帖子时,我将选择Yes。但是,我希望最后5个帖子保持特色,而其他帖子继续显示在主查询中。我不想回去每次更改选择,所以我必须找到一种方法仅排除最近的5个帖子。我在stackexchange上看到许多类似的问题,应该有一种简单的方法来管理这些特色帖子。(一种不会影响整体性能,不会创建大量查询或不需要混合sql查询的方式)
Carlisle 2012年

顺便说一句,我不确定是否为所有帖子创建一个额外的meta_key YesNo值是否是一个好主意。排除那些根本没有featured密钥的帖子将是很棒的。
卡莱尔2012年

升级到PHP 7后,该功能在我的网站上刚刚崩溃,抛出Uncaught Error: [] operator not supported for strings错误,因为原来的meta_query返回为null。您可以回落到一个空数组;如果不存在切换出绕过它$meta_query = $query->get('meta_query');$meta_query = ( is_array( $query->get('meta_query') ) ) ? $query->get('meta_query') : [];
凯文·纽金特'18

2

我想为特色帖子发布我的临时解决方案,以防某些人使用它。我pre_get_posts在这里不使用钩子,但也不query_posts是。问题是我必须使用主查询,并且必须运行一段sql查询。如果有任何专家可以检查代码并让我知道它是否还可以并且不会引起任何性能问题,我将非常高兴。如果有人有更好的方法并与我们分享,那也将很棒。

创建特色帖子查询

<?php 

$featured_query = new WP_query( array(
    'meta_key'       =>'featured', 
    'meta_value'     =>'yes', 
    'posts_per_page' => 5, 
    'no_found_rows'  => true
    )
);

while ($featured_query->have_posts()) : 

    $featured_query->the_post(); 
    //Stuff...

endwhile; 
wp_reset_postdata(); 

?>

创建主查询,排除具有meta_key特征的帖子,将排除范围限制为5个最新帖子,并显示所有其他帖子。

<?php 

$excludeposts = $wpdb->get_col( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = 'featured' AND meta_value != '' ORDER BY post_id DESC LIMIT 0, 5" );

$main_query = new WP_Query( array(
    'post__not_in' => $excludeposts, 
    'paged' => $paged 
    ) 
);  

while ($main_query->have_posts()) : 

    $main_query->the_post();
    //Stuff...

endwhile;

?>

0

作为对@Carlisle的回应,如果您想排除标记为精选的最近5条最新帖子,则可以执行以下操作。将posts_per_page更改为要排除的数量,将meta_query更改为您指定特色类别的方式。

function cmp_exclude_featured_posts($query) {
    $exclude = array();  //Create empty array for post ids to exclude
    if ( $query->is_main_query() ) {
            $featured = get_posts(array(
                'post_type' => 'post',
                'meta_query' => array(
                    array(
                        'key' => 'featured',
                        'value' => '1',
                        'compare' => '==',
                    ),
                ),
                'posts_per_page' => 2
            ));

            foreach($featured as $hide) {
                $exclude[] = $hide->ID;
            }   

            $query->set('post__not_in', $exclude);
        }
}

add_filter( 'pre_get_posts', 'cmp_exclude_featured_posts' );
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.