1

the_author() filter hook can be used to modify the output of the_author(). When using the hook, is it possible to know which PHP file generates which call to the_author()?

For example, say I have this custom function attached to the_author() filter hook, which modifies the_author() output:

add_filter("the_author", "change_author");
function change_author($author) {
    $author = "NEW AUTHOR!";

    return $author;
}

When I load my page, I can see this change occur in 5 separate sections:

  • Once in the header (from file header.php).
  • Twice in the body (from file page.php).
  • Twice in the footer (from file footer.php).

Inside my function change_author(), is there any way to know which PHP file is currently making the call to the_author()?

My motivation for asking is because I'd like to change the author for only certain sections, i.e. only when the_author() is called from a specific file (my_file.php). For all other instances of the the_author() I want to leave the output unmolested. I'm just wondering if that's possible to accomplish using the_author() filter hook.

  • 1
    You can't really based on the file, but there could be some logic you could use to do something similar. Can you describe the circumstances in more 'business-logic' terms? For example, you want to change filter the author "when displayed for the current main post, but not for other posts listed in a widget". – Jacob Peattie Jan 28 at 12:24
  • 1
    Have you considered calling a custom function from my_file.php instead of the_author? What you're asking for is not a trivial thing, and is beyond most developers capabilities, the result may not be exactly what you want either, specifically you'll need the reflection API to be available. I can guarantee there are better ways to solve your problem of displaying different things on your template, such as using a custom function – Tom J Nowell Jan 28 at 12:38
  • @TomJNowell Directly editing my_file.php is indeed my fall back solution. I would have to copy a theme file from parent to child to do it. So before I do that, i was wondering if I could achieve the same with custom code in my child theme. I realize this approach is probably the more advantageous solution. But one goal of my question is to at least learn if what I want is at all possible. If not for this exercise, but for the future. – cag8f Jan 28 at 15:04
  • 1
    @JacobPeattie Sure I can try to explain in terms you've described. My theme displays a 'featured posts' section at the bottom of each individual post. It does so via a theme file: related_posts.php. In it, it displays the author for a handful of posts, each time using the_author(). I want to return a blank string for the_authoer() in each of these cases. Does that make sense? – cag8f Jan 28 at 15:06
1

You can determine the calling files using debug_backtrace in PHP, which will give you the backtrace of the functions called and the file called from. WP core provides wp_debug_backtrace_summary, which makes doing things like this easier. Using the condition stated in your question of being called from my_file.php you could do something like this:

add_filter( 'the_author', 'change_author' );
function change_author($author) {
    if ( false !== strpos( wp_debug_backtrace_summary(), 'my_file.php' ) ) {
        $author = "NEW AUTHOR!";
    }

    return $author;
}

By not passing any args to wp_debug_backtrace_summary it will output the summary as a string. Then we just use strpos to check if my_file.php is included in the output as a calling file and do the changes.

As mentioned by others, this might not be the best approach, but it is easily doable.

| improve this answer | |
  • OK thanks for that. That could probably accomplish what I want. On the other hand, the use of strpos is a bit fragile, so I can see how it might not be the most advantageous solution. That said, I may play around with it, just to see if it will work (even if I don't actually end up using it). – cag8f Jan 28 at 15:09
1

From your comment:

Sure I can try to explain in terms you've described. My theme displays a 'featured posts' section at the bottom of each individual post. It does so via a theme file: related_posts.php. In it, it displays the author for a handful of posts, each time using the_author(). I want to return a blank string for the_authoer() in each of these cases. Does that make sense?

You might be able to achieve this with normal template tags. We could implement it as the following logic:

  1. If we are viewing a single post.
  2. If the the_author() function is being used for any other post than the current individual post.

This could work because the author for the current main post isn't likely being displayed anywhere else on the page, because the related posts can't be the current post, by definition.

The reason we can do this is because get_the_ID() will return the post ID of the post whose author is being displayed, while get_queried_object_id() will get the ID of the full post that's being displayed, no matter where we use it. So we just need to compare them:

add_filter(
    'the_author',
    function( $author ) {
        // We only want our filter to affect single post views.
        if ( is_single() ) {
            // If the author is being displayed for any post other than the current post.
            if ( get_the_ID() !== get_queried_object_id() ) {
                $author = '';
            }
        }

        return $author
    }
);

One thing you'll need to consider, though, is that if the theme is outputting markup around the author name, that will still be output. The only way to remove that would be to modify the template.

| improve this answer | |
  • OK wow--that's some good critical thinking there. What you've described should do exactly what I want, and I am indeed impressed. Bravo. But, I think you'll agree the solution is relatively unique to my situation. The alternate solution proposed by @Tim Elsass, while possibly a bit more fragile, is more of a general solution. I'm torn as to which I should mark as the answer! First world problems I guess. I'm actually leaning towards Tim's. My question was more of a more general question, so his answer is a bit more applicable. What do you think? – cag8f Jan 30 at 6:37
  • I should say though, I that I have not actually tested either suggestion. – cag8f Jan 30 at 6:38
  • "One thing you'll need to consider, though, is that if the theme is outputting markup around the author name, that will still be output. The only way to remove that would be to modify the template." Yes I know. I didn't want to mention that in my question, but as you note, returning a blank string for the_author() will indeed leave my page with an empty HTML element, which is undesirable. In light of that, I will most likely go with editing the template (in my child theme), rather than filtering the_author(). I hope I didn't betray anyone's trust. But I was genuinely curious to know. – cag8f Jan 30 at 6:40
  • "In light of that, I will most likely go with editing the template (in my child theme), rather than filtering the_author()." Would you agree that editing the template is the most proper course of action in this case? In this case, copying the template from parent to child, then editing it, won't take long. In fact, I've already done it, and it works as expected. – cag8f Jan 30 at 6:41
  • Editing the template is absolutely the "correct" most foolproof way to control what information appears where, but that's not what you asked. The technique in my answer, of using conditionals and comparing the queried object, can be useful in many circumstances though. Using wp_debug_backtrace_summary() in this fashion is a bit of a hack, to be perfectly honest. As the name suggests, it's for debugging. – Jacob Peattie Jan 30 at 6:57

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.