如何强制查询条件?

时间:2014-01-18 作者:Chip Bennett

有一个长期存在的WordPress核心bug(#16373) 其中,如果在查询字符串中注册并存在自定义查询变量,则不会设置查询is_front_page() 是的,即使\'page\' == get_option( \'show_on_front\' ). 完整的详细信息在trac票证中,但最终结果是首页返回无效页面,而不是get_option( \'page_on_front\' ).

我有一个特定的用例,在这个用例中,我需要将自定义查询变量传递给首页上的查询字符串(使用表单传递已注册的查询变量,这些查询变量反过来又用于过滤主题选项-前端主题选项演示)。上述trac票证因无效而关闭,因此我需要解决问题。

我可以很容易地强制使用首页模板,如下所示:

function themeslug_force_front_page_template( $template ) {
    if ( \'\' != get_query_var( \'foobar\' ) ) { // Registered custom query var
        return get_front_page_template();
    }
    return $template;
}
add_filter( \'template_include\', \'themeslug_force_front_page_template\' );
但是,基础查询条件不受影响。因此,任何代码都依赖于is_front_page() 存在true (例如,仅显示在站点首页上的滑块)仍然无法正确渲染。

我已尝试修改$querypre_get_posts, 但这似乎不起作用:

function themeslug_force_static_front_page( $query ) {
    if ( $query->is_main_query() ) {
        if ( \'page\' == get_option( \'show_on_front\' ) ) {
            if ( \'\' != get_query_var( \'foobar\' ) ) { // Registered custom query var
                $query->set( \'page_id\', get_option( \'page_on_front\' ) );
                $query->set( \'is_home\', false );
                $query->set( \'is_page\', true );
                $query->set( \'is_front_page\', true );
            }
        }
    }
}
add_action( \'pre_get_posts\', \'themeslug_force_static_front_page\' );
不会修改查询条件。我是否在回拨中尝试错误?是否有其他/更好的方法来强制查询条件,尤其是is_front_page()?

编辑请注意,设置page_id does 在中工作pre_get_posts 回调:

$query->set( \'page_id\', get_option( \'page_on_front\' ) );
如果我省略template_include 过滤器,显示的页面实际上是分配给首页的页面;然而get_page_template() 使用,而不是get_front_page_template(). 所以,设置page_idpre_get_posts 确实导致is_page() 是真的。但是前面提到的bug阻止了is_front_page() 从设置为true.

根据@toscho的请求编辑2,这里是一些查询变量代码,用于上下文。

注册查询变量:

/**
 * Add options-related query variables
 */
function themslug_add_theme_demo_query_vars( $qvars ) {
    $qvars[] = \'demo_foo\';
    $qvars[] = \'demo_bar\';
    $qvars[] = \'demo_baz\';
    return $qvars;
}
add_filter( \'query_vars\', \'themeslug_add_theme_demo_query_vars\' );
(其中foo, bar, 和baz 是主题选项-背景、各种颜色等)

它们的使用方法只是向主题选项添加一个过滤器——这部分超出了问题的范围,所以我将在这里省略它。

它们通过自定义小部件在前端输出。小部件输出只是一个表单。以下是其中一个表单字段的示例:

<h3>Foo</h3>
<input name="demo_foo" id="demo_foo" class="pickcolor"  type="text" value="<?php echo $foo_setting; ?>" data-default-color="<?php echo $foo_setting; ?>" />
提交时生成的查询字符串:

www.example.com/?foo=some_value

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

你检查过is_front_page() 是否导致返回false?

我可以通过跟踪trac记录单的设置来重现该问题。在我的例子中,在这个函数中is_page() 正在返回false.

我想这是因为$wp_query->set() 对于page_idis_page 只会导致query_vars 要更改,您不需要更改“查询状态”本身。

我可以通过在代码中附加这两行代码来创建一个解决方案:

$query->is_page = true;
$query->queried_object = get_post(get_option(\'page_on_front\') );
这导致(在我的设置中)页面正确显示在frontpage上(尽管URL中存在query\\u var),并且is_front_page() 正在返回true.

我希望这对你有进一步的帮助。

如果你看看WP_Query 类,您将看到有一个变量$query_vars 还有一个变量$is_page.

这个set 您使用的函数($query->set( \'is_page\', true );) 只设置了query var:

function set($query_var, $value) {
    $this->query_vars[$query_var] = $value;
}
它不会更改保存在中的状态信息$query->is_page = true, 相反,它设置查询变量$query->query_vars[\'is_page\'] = true.

如果您来自OOP方法并理解WP_Query::set() 作为一个经典的类setter函数,事实并非如此。

SO网友:Otto

我也回答了Trac问题,但我认为这里的基本问题比这个简单得多。

您将demo\\u foo、demo\\u bar、demo\\u baz作为“查询变量”挂接,但它们不是;至少,不是有意的。

什么时候?foo=条形字符串在URL通常被称为查询字符串之后,“查询变量”实际上只是影响主查询的变量。如果不挂接变量,它不会消失,只是不会被主要的WP\\u查询对象读取。

对你来说,这似乎正是你想要的。您的变量是主题选项,它们不是主查询(从数据库获取帖子)的一部分。你不是用它们来选择要显示的帖子,而是用它们来设置主题选项等等。

如果不将它们作为query\\u vars挂钩,那么它们根本不会影响主要的WP\\u查询对象。您必须从主$\\u get superglobal获取它们,而不是使用get\\u query\\u var,并且必须对它们执行适当的清理,以防止反射性XSS攻击(使用esc\\u attr或任何适当的方法),但这应该通过首先消除导致问题的代码来解决您的主要问题,而不是添加额外的解决方法。

结束

相关推荐

使用新的WP-Query()从循环中过滤后期格式;

嗨,我目前正在为我的博客构建一个主题。下面的代码指向最新的帖子(特色帖子)。因为这将有一个不同的风格比所有其他职位。然而我想过滤掉帖子格式:链接使用我在循环中定义的WP查询,因为它给我带来了更多的灵活性。我该怎么做呢? <?php $featured = new WP_Query(); $featured->query(\'showposts=1\'); ?> <?php while ($featured->have_post