the_content and is_main_query

I am filtering the content with the the_content filter. Everything works perfect, excerpt that my changes are applied to custom queries as well. My changes appear in the sidebar as well if the widget uses a custom query

To counter that, I’m using is_main_query() to target the main query only, but it is not working. Changes are simply still applied to all queries through out. What is funny though, all other conditional checks like is_single() and is_category() is working if I target specific pages, except that all changes affect any other custom query on that page, whether I use is_main_query() or not

Am I missing something here. How do I apply my changes to the main query only using the the_content filter

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:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

To be honest, the function in_the_loop() is what you are looking for:

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;
}

What in_the_loop does is to check if global for $wp_query (that is the main query object) of the current post is -1 < $current_post < $post_count.

That happens when the main query is looping, because before loop starts, current post is -1, and after loop ends, current post is reset to -1 again.

So, if in_the_loop() is true, it means that the main query object is looping, which is what you need in this case (and is the same result of adding the action on loop_start and removing on loop_end, like the answer @ialocin wrote; in fact it works for the same reason, and got my +1).

Benefit of @ialocin’s approach is when you want to target a different query object than main one, because in_the_loop() only works for main query.

Method 2

This is merely an addition to @Otto’s answer. Just to make it a little bit better understandable. Basically what @Otto is saying, you have to reverse the logic, that means: if you can reliably determine the main query, then you can add – and remove – your hooking into the the_content filter.

For example the main query can reliably be recognized at the pre_get_posts action, so this would work:

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' );
    }
}

As you are supposed to remove the filter when it is not longer needed, I’m thinking the loop_end action should be a good place for that and as its counterpart we can use loop_start. Which would look like this:

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' );
    }
}

Method 3

You’re using is_main_query() incorrectly. The global is_main_query() function returns true unless the global $wp_query variable has been redefined.

There is probably no 100% reliable way to tell, from inside a the_content filter, whether or not the current Loop you’re in is the main query or not. The content filter just filters content. It doesn’t have any form of ability to know what loop it is being used for.

Instead, you should add your filter when you need it, then remove it when you don’t.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x