the_content和is_main_query


15

我正在使用过滤the_content器过滤内容。一切正常,摘录内容也包括我的更改也应用于自定义查询。如果小部件使用自定义查询,我的更改也会显示在边栏中

为了解决这个问题,我is_main_query()仅将主要查询作为目标,但它不起作用。更改仍然会一直应用于所有查询。什么是有趣的,虽然,所有其他条件检查像is_single()is_category()工作,如果我针对特定的网页,除了所有更改会影响任何其他自定义查询页面上,我是否使用is_main_query()与否

我在这里想念什么吗?如何仅使用the_content过滤器将更改应用于主查询

add_filter('the_content', 'custom_content');

function custom_content($content){

    if(is_main_query()){ // << THIS IS NOT WORKING
        // My custom content that I add to the_content()    
    }
    return $content;
}

Answers:


11

老实说,该功能in_the_loop()是您要寻找的:

add_filter( 'the_content', 'custom_content' );

function custom_content( $content ) {
    if ( in_the_loop() ) {
        // My custom content that I add to the_content()    
    }
    return $content;
}

什么in_the_loop做的是检查,如果全球对$wp_query(即主查询对象)当前职位的是-1 < $current_post < $post_count

在主查询循环时会发生这种情况,因为在循环开始之前,当前发布为-1,而在循环结束之后,当前发布再次重置为-1。

因此,如果in_the_loop()为true,则表示主查询对象正在循环,在这种情况下,这是您所需要的(并且loop_start与在loop_end@ialocin回答中所添加的操作相同,并在on上进行删除的结果相同;实际上,它可以工作出于同样的原因,得到了我的+1)。

@ialocin方法的好处是,当您要针对与主要对象不同的查询对象时,因为它in_the_loop()仅适用于主要查询。


我没有在网站搜索或在线搜索中遇到此问题。一种有效的隐藏宝石。每个解决方案都使用is_main_query,真的认为没有人对此进行全面测试。谢谢您的
宝贵

1
@PieterGoosen很高兴它起作用。那是一个非常古老的功能,它从什么is_main_query都不是的时候就直接出现了。
gmazzap

您看,这是我想念的地方,我不是老手记:-),在3.3中加入了Wordpress。
Pieter Goosen 2014年

2
@GM您介意将此添加到您的答案中。这对可能偶然发现此答案的其他人很有用。像我这样的大多数人都不会阅读评论:-)
Pieter Goosen 2014年

1
@PieterGoosen完成了:)
gmazzap

7

这只是@Otto答案的补充。只是为了使其更容易理解。基本上,@ Otto所说的是,您必须颠倒逻辑,这意味着:如果可以可靠地确定主查询,则可以添加-或删除-连接到the_content过滤器中。

例如,可以在pre_get_posts操作中可靠地识别主查询,因此可以这样做:

function wpse162747_the_content_filter_callback( $content ) {
    return $content . 'with something appended';
}

add_action( 'pre_get_posts', 'wpse162747_pre_get_posts_callback' );
function wpse162747_pre_get_posts_callback( $query ) {
    if ( $query->is_main_query() ) {
        add_filter( 'the_content', 'wpse162747_the_content_filter_callback' );
    }
}

由于您应该在不再需要过滤器时将其删除,因此我认为该loop_end操作应该是一个不错的选择,并且可以使用它作为对等对象loop_start。看起来像这样:

add_action( 'loop_start', 'wpse162747_loop_start_callback' );
function wpse162747_loop_start_callback( $query ) {
    if ( $query->is_main_query() ) {
        add_filter( 'the_content', 'wpse162747_the_content_filter_callback' );
    }
}

add_action( 'loop_end', 'wpse162747_loop_end_callback' );
function wpse162747_loop_end_callback( $query ) {
    if ( $query->is_main_query() ) {
        remove_filter( 'the_content', 'wpse162747_the_content_filter_callback' );
    }
}

将测试这个明天。感谢您的详细说明。
Pieter Goosen 2014年

我一如既往的高兴@PieterGoosen别着急,但是要这么做,因为我还没有-至少还不够。
Nicolai 2014年

1
如果在the_content()中使用了短代码,并且该短代码启动了另一个查询,调用the_content(),重置当前的post对象,然后循环继续,该怎么办?所有过滤器均适用。这很棘手,没有被铃铛保存in_the_loop()...这就是为什么我建议始终删除唯一的过滤器,就像@Nicolai所说的那样
Jonas Lundman 17/12/3

5

您使用is_main_query()不正确。除非已重新定义全局$ wp_query变量,否则全局is_main_query()函数将返回true。

可能没有100%可靠的方法从the_content过滤器中判断当前所在的Loop是否是主要查询。内容过滤器仅过滤内容。它没有任何形式的能力来知道它被用于什么循环。

相反,您应该在需要时添加过滤器,然后在不需要时将其删除。


令人失望的是,没有使用the_content过滤器定位主查询的直接方法
Pieter Goosen

好吧,那确实不足为奇。像其他任何过滤器一样,它只是过滤事物。当调用它时,它不知道周围的上下文。甚至可能没有从适当的循环内部调用它。它无法告诉。
奥托
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.