没有为页面设置$Query->Query_var[‘POST_TYPE’]

时间:2012-06-28 作者:Zach

建造this 来自@kaiser关于能够在搜索页面上按帖子类型过滤的回复,我希望能够自动添加所有可用的公共帖子类型。因此,在@kaiser的帮助下,我想出了:

function sw_custom_post_type_includes($query) {
    $args = array(
        \'public\'   => true
    ); 
    $output = \'names\'; // names or objects, note names is the default
    $operator = \'and\'; // \'and\' or \'or\'
    $post_types = get_post_types( $args, $output, $operator ); 
    if ( !is_search() && !in_array( get_post_type(), $post_types ) )
        return;

    $query->set( \'post_type\', $post_types );
    return $query;
}
add_filter(\'pre_get_posts\', \'sw_custom_post_type_includes\');
一开始似乎效果很好,但我遇到了一个问题->除了我尝试使用&post_type=page. 我实际上得到了一个未定义的索引错误post_type. 我不明白为什么这不起作用。所以,我决定使用print_r($query->query_vars) 看看是否所有东西都被正确拉入。Low and seek-对于除页面以外的所有帖子类型,都设置了该变量。

我就此与另一位开发人员进行了讨论,他们验证了这个问题。这就是我最终使用的解决方法:

function sw_custom_post_type_includes($query) {
    if(isset($_GET[\'post_type\']) && ((!isset($query->query_vars[\'post_type\'])) || (isset($query->query_vars[\'post_type\']) && $query->query_vars[\'post_type\'] != \'nav_menu_item\'))) {
        $query->set(\'post_type\', urldecode($_GET[\'post_type\']));
    }
}
add_action(\'pre_get_posts\', \'sw_custom_post_type_includes\');
老实说,这似乎是一个奇怪的解决办法,让我困惑了几个小时。任何对此有意见的人都将获得虚拟的五分奖励。

3 个回复
最合适的回答,由SO网友:Aaron D. Campbell 整理而成

为了澄清之前答案中的一些困惑,pre\\u get\\u posts不是一个过滤器,因此您不需要返回任何内容。

我看到的唯一问题是如果:

if ( !is_search() && !in_array( get_post_type(), $post_types ) )
    return;
基本上,get\\u post\\u type()在pre\\u get\\u post期间将返回false,因为全局$post尚未设置(通常在启动循环后设置)。

我不能完全确定您何时需要所有公共帖子类型,何时不需要。如果您只想将所有搜索设置为包括所有公共帖子类型,那么您只需要检查is\\u search()。您可能还希望确保所修改的查询是主查询,而不是插件或主题文件正在创建的自定义查询。代码应如下所示:

function range_search_all_public_post_types( $q ) {
    if ( is_search() && is_main_query() )
        $q->set( \'post_type\', get_post_types( array( \'public\' => true ) ) );
}
add_action( \'pre_get_posts\', \'range_search_all_public_post_types\' );
就是这样。这将导致查询所有公共帖子类型以进行搜索。

如果要在主页上搜索所有公共帖子类型,请使用以下选项:

function range_search_all_public_post_types( $q ) {
    if ( ( is_search() || is_home() ) && is_main_query() )
        $q->set( \'post_type\', get_post_types( array( \'public\' => true ) ) );
}
add_action( \'pre_get_posts\', \'range_search_all_public_post_types\' );

UPDATE:

您遇到的问题是public\\u queryable设置为false的post\\u类型所特有的。您基本上希望所有公共类型都能工作,即使它们不可公开查询。为此,请使用以下代码:

function range_search_all_public_post_types( $q ) {
    if ( is_search() && is_main_query() && \'\' == $q->get( \'post_type\' ) && ! empty( $_GET[\'post_type\'] ) && post_type_exists( $_GET[\'post_type\'] ) && get_post_type_object( $_GET[\'post_type\'] )->public )
        $q->set( \'post_type\', $_GET[\'post_type\'] );
}
add_action( \'pre_get_posts\', \'range_search_all_public_post_types\' );
基本上,如果一个post\\u类型在URL中,但不在QP\\u查询中,那可能是因为它不可公开\\u查询,如果是这样,我们会修复它。检查内容如下:

这是搜索页面吗

  • 指定的URL post\\u类型是否存在
  • 指定的URL post\\u类型是公共的吗
  • 如果所有这些都是真的,它会将post\\u类型设置为URL中的类型。

    SO网友:kaiser

    当我回答这个问题时,这是一个后续问题,并且在对这里的问题进行了大量评论之后,我非常确定,您在某个地方有另一个过滤器或条件,阻止您检索页面的结果。99%的可能性是你的问题。你最好从一个空白的普通安装开始,试着只运行这个过滤器来证明它工作正常。然后走进来,开始删除/注释所有自定义内容,停用插件等,直到你知道发生了什么。

    SO网友:Christian

    你写的

    if ( !is_search() && !in_array( get_post_type(), $post_types ) )
        return;
    
    如果page 不在您的$post_types 数组有一个空的return;

    实际上,我不明白为什么要添加此安全性,只有在实际需要时才调用此函数,这要归功于pre_get_posts 滤器

    您只需更改退货:

    function sw_custom_post_type_includes($query) {
        $args = array(
            \'public\'   => true
        ); 
        $output = \'names\'; // names or objects, note names is the default
        $operator = \'and\'; // \'and\' or \'or\'
        $post_types = get_post_types( $args, $output, $operator ); 
        if ( !is_search() && !in_array( get_post_type(), $post_types ) )
            return $query;  //#### keep it unchanged instead of removing everything ####
    
        $query->set( \'post_type\', $post_types );
        return $query;
    }
    add_filter(\'pre_get_posts\', \'sw_custom_post_type_includes\');
    
    这只是一个想法,我没有尝试

    结束