1

I want to use

add_filter('the_content',...........)

however, I want that filter only to affect main post's content. See phseudo-example:

<html>
.......
<meta decsription>.....the_content...</meta>
.......
<left_widget>....the_content...</left_widget> 
.......
<MAIN_POST>....the_content...</MAIN_POST>         <----------------- I want only this to be affected
......

How to achieve? (of course, out-of-question is the category pages, where post_contents are listed)

0
2

Found solution here, to use in_the_loop() (but read comment below my answer too):

add_filter( 'the_content', 'custom_content' );

function custom_content( $content ) {
    if ( in_the_loop() ) {
        // ....
    }
    return $content;
}
1
  • 2
    there are all kinds of reasons to do the loop in the head and then rewind it before showing actual content. in_the_loop will just return happily true in the header footer or sidebar. By using it you are trusting theme developers of not doing anything weird. – Mark Kaplun Feb 3 '17 at 16:28
2

This method doesn't work. I leave this answer only as reference.

If I understand correctly, the easier way is to check if you are in the main query inside the filter's callback:

add_filter( 'the_content', 'cyb_filter_content' );
function cyb_filter_content( $content ) {

    if( is_main_query() ) {

        // Work with $content here

    }

    return $content;

}

But this DOESN'T WORK. Why?

is_main_query() does this:

function is_main_query() {
    global $wp_query;
    return $wp_query->is_main_query();
}

So, it does not check if the query of the current loop is the main query, it checks if the global $wp_query object is the main query; and the global $wp_query object is always the main query unless it has been modified, which is something, let's say, unusual and often not recommended. So, is_main_query() returns true almost everywhere and everytime.

9
  • yes, you understand, but that is not complete. because, is_singular returns true ,even while outputing content in widget or in <HEAD> description meta tag.. – T.Todua Feb 2 '17 at 20:45
  • Mmmm ..... Let me check it and think about it. – cybmeta Feb 2 '17 at 20:46
  • Added is_main_query(); can you try it and give some feedback? – cybmeta Feb 2 '17 at 20:52
  • 1
    Even seeing the soruce code, It is hard for me to understand why in_the_loop() works to check if you are in the main query and is_main_query() doesn't when used inside the filter content; both use the global $wp_query. – cybmeta Feb 2 '17 at 21:45
  • 1
    is_main_query() is good candidate for worst named function in core, it does something absolutely different from what you would guess from name — checks if global query had been overridden. – Rarst Feb 2 '17 at 22:09
1

This is quite simple, see code below.

add_filter( 'the_content', 'my_the_content_filter' );
function my_the_content_filter( $content ){
    // If it is not page named debug, do nothing
    if( $GLOBALS['post']->post_name != 'debug' )
        return $content;

    // do actions...
    $content = 'my super cool new content';
    return $content;
}
2
  • but that uses the static debug title. however, thanks for hint. I need the filter for 1000 pages.. I think, the_title() may help.. – T.Todua Feb 2 '17 at 20:43
  • 1
    anything can set the global $post, it is very unreliable indication for anything – Mark Kaplun Feb 3 '17 at 16:11
1

Problem

Hooking into the_content does not guarantee that we're in the loop.

Solution

Hook into pre_get_posts to exclude certain queries. Hook into the loop via the_post before hooking the_content.

Details

Add action to pre_get_posts to specifically see if the page is singular.

add_action( 'pre_get_posts', 'wpse_106269_pre_get_posts', 10, 1 );
function wpse_106269_pre_get_posts( $query ) {
  if( is_singular() ) {
    add_action( 'the_post', 'wpse_106269_the_post', 10, 2 );
  }
}

Add an action to the_post. This action hook is fired for each post when we're in the loop. Once we're in the_post, we know that we're in the loop, so we can add a filter to the_content.

function wpse_106269_the_post( $post, $query ) {
  remove_action( 'the_post', 'wpse_106269_the_post', 10, 2 );    
  add_filter( 'the_content', 'wpse_106269_the_content', 10, 1 );
}

To make sure that the_content filter is only fired in the_post, remove it so that it doesn't get fired in the future unless it's added again by the_post action hook.

function wpse_106269_the_content( $content ) {
  remove_filter( 'the_content', 'wpse_106269_the_content', 10, 1 );
  //* Do something with $content
  return $content;
}
2
  • interesting one... however, it doesnt guarantee,that it ahppens only on singular page/post... it will affect Category listings too (where 10 posts are shown). right? – T.Todua Feb 11 '17 at 9:15
  • it would have. I added a check to see if the page is_singular() which fill now conditionally fire the_post. – Nathan Johnson Feb 11 '17 at 15:03
0

This is probably an impossible task. the_content and its friend the_excerpt lack context and it is just impossible to guess the context from looking at the various global variables as they might have been altered.

Some themes provide actions to indicate that they are starting to output the post content but this is far from being standard.

The only way to work with it is to assume other plugin and theme developers are smart and don't use the_content for anything which do not actually display the post content. (far fetched assumption)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.