问题描述

我正在使用 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;
}

最佳解决方案

说实话,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

当主查询循环时,因为 before 循环开始,当前的帖子是-1,而循环结束后,当前的帖子将被重新设置为-1 。

所以,如果 in_the_loop()是真的,这意味着主查询对象是循环的,这就是你在这种情况下需要的 (和 loop_start 上添加操作相同的结果,并且在 loop_end 上删除,就像 @ialocin 写的一样; 事实上它的工作原理相同,得到了我的+1) 。

因为 in_the_loop()仅适用于主查询,因此 @ ialocin 的方法的优点是当您要定位与主要查询对象不同的查询对象时。

次佳解决方案

这只是 @ 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' );
    }
}

第三种解决方案

您正在使用 is_main_query()。 global is_main_query() 函数返回 true,除非全局 $ wp_query 变量被重新定义。

从 the_content 筛选器中可以看出,您当前的 Loop 是否是主查询,可能没有 100%可靠的方式。内容过滤器只是过滤内容。它没有任何形式的能力知道它被用于什么循环。

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

参考文献

注:本文内容整合自 Google/Baidu/Bing 辅助翻译的英文资料结果。如果您对结果不满意,可以加入我们改善翻译效果:薇晓朵技术论坛。