如何从搜索结果中排除页面

时间:2017-03-14 作者:SilverLink

我想排除pages 从搜索结果中,找到了许多方法,并想知道为什么要使用!is_admin()is_main_query() 哪种方式更好。

add_filter(\'pre_get_posts\',\'search_filter\');
function search_filter($query) {
    if ($query->is_search) {
        $query->set(\'post_type\', \'post\');
    }
    return $query;
}
<小时>
add_filter(\'pre_get_posts\',\'search_filter\');   
function search_filter($query) {
    if ( !is_admin() && $query->is_search) {
        $query->set(\'post_type\', \'post\');
    }
    return $query;
}
<小时>
add_action(\'pre_get_posts\',\'search_filter\');    
function search_filter($query) {
if ( !is_admin() && $query->is_main_query() ) {
        if ($query->is_search) {
            $query->set(\'post_type\', \'post\');
        }
    }
}

2 个回复
最合适的回答,由SO网友:birgire 整理而成

请注意,当我们使用:

$query->set( \'post_type\', \'post\' );
然后我们将覆盖所有可搜索的帖子类型,而不仅仅是page 岗位类型。

在某些情况下,这可能很好,我们已经使用了您的一些pre_get_posts 符合我们需求的片段。

但有时我们不想用这种方式来解决问题。这里我们讨论这种情况。

Using the register_post_type_args filter.

如果未指定post类型,则WP_Query 搜索使用任何可搜索的帖子类型,namely:

$in_search_post_types = get_post_types( array(\'exclude_from_search\' => false) );
注册帖子类型时,可以设置exclude_from_search 参数设置为false以将其从搜索中排除。

我们可以将其修改为page post类型设置:

add_filter( \'register_post_type_args\', function( $args, $name )
{
    // Target \'page\' post type
    if( \'page\' === $name )
        $args[\'exclude_from_search\'] = true;

    return $args;
}, 10, 2 );
更多关于register_post_type() here.

Examples

以下是使用上述过滤将页面帖子类型从搜索中排除的示例:

前端的主查询搜索

https://example.tld?s=testing
辅助查询,如:

$query = new WP_Query( [ \'s\' => \'testing\' ] );
辅助查询,如:

$query = new WP_Query( [ \'s\' => \'testing\', \'post_type\' => \'any\' ] );

Some notes on queries with pre set post types:

让我们考虑一下帖子类型固定的情况,例如:

 $query = new WP_Query( [ \'s\' => \'testing\', \'post_type\' => [ \'page\', \'post\'] ] );
如果post类型由某个数组设置$post_type, 然后我们可以过滤\'page\' 把它拿出来

if( is_array( $post_type )  && count( $post_type ) > 1 )
{
    $post_type = array_filter( 
        $post_type, 
        function( $item ) { return \'page\' !== $item; } 
    );
}
如果我们不能直接访问该阵列,我们可以使用。pre_get_posts 要从post类型数组中删除“页面”,请在get/set 方法WP_Query. 以下是前端的主搜索查询示例:

add_action( \'pre_get_posts\', function search_filter( \\WP_Query $query )
{
    if( ! $query->is_search() || ! $query->is_main_query() || ! is_admin() )
        return;

    $post_type = $query->get( \'post_type\' );

    if( is_array( $post_type )  && count( $post_type ) > 1 )
    {
        $post_type = array_filter( 
            $post_type, 
            function( $item ) { return \'page\' !== $item; } 
        );
        $query->set(\'post_type\', $post_type );
    }

} );
为什么我们在这里检查数组计数>1?

那是因为我们应该小心移除\'page\' 例如:

 $query = new WP_Query( [ \'s\' => \'testing\', \'post_type\' => [ \'page\' ] ] );

 $query = new WP_Query( [ \'s\' => \'testing\', \'post_type\' => \'page\' ] );
作为空数组或空字符串,对于post类型:

 $query = new WP_Query( [ \'s\' => \'testing\', \'post_type\' => [] ] );

 $query = new WP_Query( [ \'s\' => \'testing\', \'post_type\' => \'\' ] );
将退回到\'post\' 岗位类型。

请注意:

 $query = new WP_Query( [ \'s\' => \'testing\', \'post_type\' => \'page, post\' ] );
不支持,因为生成的帖子类型为\'pagepost\'.

在这些情况下,我们无法直接访问WP_Query 对象,我们可以使用以下技巧停止查询\'post__in\' => []1=0 在搜索中查询部分或甚至使用posts_pre_query 过滤或使用一些更高级的方法。关于这一点,这个网站上有很多答案。Thisthis 这是我现在回忆起来的。

这个null 案例:

 $query = new WP_Query( [ \'s\' => \'testing\', \'post_type\' => null ] );
回落到\'any\' 职位类型:

希望有帮助!

PS:

还要注意代码片段中的不一致性,因为两者都有

add_filter(\'pre_get_posts\',\'search_filter\');   
以及

add_action(\'pre_get_posts\',\'search_filter\');   
这被认为是一个动作,但不会有任何区别,因为动作在幕后被包装为过滤器。

SO网友:Ben Casey

pre_get_posts 将在admin和frontend中运行,您可以使用它筛选admin用户看到的帖子以及frontend结果。正在添加! is_admin() 将确保该代码只影响前端。

is_main_query() 将确保您只影响帖子的查询,而不影响导航栏中的菜单项或侧栏中的帖子列表。建议使用该选项。

如果不清楚,请告诉我,

相关推荐

无法在模板函数.php中使用IS_HOME

我试图在标题中加载一个滑块,但只在主页上加载。如果有帮助的话,我正在使用Ultralight模板。我正在尝试(在template functions.php中)执行以下操作:<?php if ( is_page( \'home\' ) ) : ?> dynamic_sidebar( \'Homepage Widget\' ); <?php endif; ?> 但这行不通。现在,通过快速的google,我似乎需要将请