使用$QUERY->集合超级混淆‘pre_get_post’行为

时间:2017-07-14 作者:TheBigK

几个小时来,我一直在为这个奇怪的问题发愁,需要一些人帮助我弄清楚到底发生了什么。请允许我解释我的设置,然后是行为和问题。

设置:

我已将“帖子页面”设置为域。com/search/where我打算列出我的所有帖子。

由于我需要一个自定义布局来显示我的帖子,我在“template\\u include”挂钩中进行了以下重定向:

/*Use custom template to render posts on /search/ */
if ( is_home() ) {
    return plugin_dir_path( __FILE__ ) . \'partials/display-speaker-list.php\';
}
“我的帖子”列表还显示与每篇帖子相关的标签。我希望这些标签可以点击。当用户单击任何标记时,我想使用单击的标记作为关键字来过滤帖子。每个帖子显示标签的HTML如下所示:

 <a href="<?php echo esc_url( home_url(\'/\') . \'search/?tag=\' . str_replace(\' \', \'+\', $topic ) ); ?>" class="btn btn-outline-primary" role="button"><?php echo esc_html( $topic ); ?></a>
为了让搜索工作正常进行,我决定使用“pre\\u get\\u posts”挂钩。这就是奇怪的事情开始发生的地方。看看我执行的代码pre_get_posts :

/* Filter posts using the tag   
public function io_speakers_pre_get_posts( $query ) {

    if ( $query->is_main_query() && $query->is_home() ) {
        $query->set(\'tag\', $_GET[\'tag\']);
        return $query;
    }
    return $query;
}
以下是奇怪的行为:

如果我删除$query->set(\'query_var\', \'value\'); 语句,WordPress返回所有帖子,完全忽略search/?tag=xyz 查询但即使我将其设置为随机或空,它也能工作。也就是说,如果我将该行更改为$query->set(\'\', \'\');

简而言之,WordPress希望我$query->set(WHATEVER); 在该条件下,它将确认“tag”参数的存在。否则它只会返回所有帖子。

我的问题是:

到底发生了什么$query->set()? $query->(blah, blah) 为了正常工作/search/?topic=someTopic 而不是/search/?tag=someTopic?

-K级

2 个回复
SO网友:Tom J Nowell

您不需要添加pre_get_posts 过滤器用于?tag=xyz 要工作,WordPress中的URL应该已经可以这样工作了。如果您可以将其写入字符串并将其传递给WP_Query 然后,您可以使用? 添加其他查询参数。这是假设主查询没有被替换为新查询,或者其他插件没有干扰

$query->set()到底发生了什么

在执行查询之前,它通过pre_get_posts 过滤器,以及set 更改查询变量。就是这样,没有奇怪的巫毒

为什么需要我在$query->(诸如此类)中设置任何随机内容才能正常工作

不应该这样,但当涉及头版设置时,事情可能会变得有点奇怪,因为它改变了什么is_homeis_front_page 意思是在主查询中,这意味着is_front_page 无法使用,因为计算它的逻辑尚未运行

如果我想按/搜索/?topic=某个主题而不是/搜索/?标记=某个主题

做你一直在做的事,但不要$_GET[\'tag\']$_GET[\'topic\']

模板上的最后一条注释我在你的问题中看到了这一点:

return plugin_dir_path( __FILE__ ) . \'partials/display-speaker-list.php\';

该模板需要一个标准的post循环,才能使任何一个都正常工作。如果以下任何一项为真,则不会:

Aquery_posts 呼叫AWP_Query 使用循环get_posts这些都不是主要查询,因此pre_get_posts 过滤器将无法通过检查,并在不进行修改的情况下继续运行

顺便提一下,您是否考虑过更改标记permalinks,并使用真正的归档URL,而不是使用URL参数来攻击主博客页面?

SO网友:Tom J Nowell

因此,我在自己的网站上有一点曲线球设置,但我意识到它可以用来完全回避您的问题。

例如,在我自己的网站tomjn上。com,我的主页是一个普通主页,设置为最新帖子,然后使用home.php 作为的模板。

然而,我的文章页面根本不是一个页面,它是一个由重写规则支持的存档。由于这是一条重写规则,我可以完全控制查询变量:

// add my articles/ archive, and pagination rules!
// I also added a query variable so that I know
// if I\'m on this page or not
function tomjn_posts_rewrite_rule() {
        add_rewrite_rule(\'articles/page/([0-9]{1,})/?\',\'index.php?paged=$matches[1]&toms_custom_posts=true\',\'top\');
        add_rewrite_rule(\'articles/?\',\'index.php?toms_custom_posts=true\',\'top\');
}
add_action(\'init\', \'tomjn_posts_rewrite_rule\', 10, 0);

// does the same thing as the next function but
// specifically to the main query. Seems redundant
// but it was necessary for some reason :/
function tomjn_template_redirect_intercept () {
        global $wp_query;
        if ( $wp_query->get( \'toms_custom_posts\' ) ) {
                $wp_query->is_home = false;
                $wp_query->is_archive = true;
                $wp_query->show_posts = true;
        }
}
add_action( \'template_redirect\', \'tomjn_template_redirect_intercept\' );

// WP has some ideas about what query vars are set,
// I have my own, lets make sure this is an archive,
// not the homepage, and that posts are fetched
// but only if my custom query var is set
function _tomjn_setup_posts_page( $query, \\WP_Query $q ) {
        if ( $q->is_main_query() && $q->get( \'toms_custom_posts\' ) ) {
                $q->is_home = false;
                $q->is_archive = true;
                $q->show_posts = true;
        }
        return $query;
}
add_filter( \'posts_request\', \'_tomjn_setup_posts_page\', 1, 2 );

// whitelist my custom query var
function tomjn_rewrite_query_vars( $vars ) {
        $vars[] = \'toms_custom_posts\';
        return $vars;
}
add_filter( \'query_vars\', \'tomjn_rewrite_query_vars\' );
现在我相信你知道如何改变tomthebigk 等等,然后换掉articles 等等

我也相信你知道如何使用template_include 加载您自己选择的模板文件,否则将加载archive.php.

请注意,安装代码后需要刷新永久链接。

一般的想法是添加一个重写规则来创建新的存档。在查询参数中,添加一个标记,以便知道它何时处于活动状态。但是WP不知道它是一个归档文件,所以代码截取了主查询并进行了一些调整,以便知道它是一个归档文件

作为旁白,测试/articles/?tag=php 在我的网站上使用此代码。它应该与您设置的内容配合使用,但情况显然不是这样。所以我提供了一个替代的,有点疯狂的解决方案

hint: 如果您第三次复制重写规则,并在主题中添加一些正则表达式魔术,那么您的/search/?topic=xyz 成为/search/topic/xyz

结束

相关推荐