Debugging WordPress Filters, the_content Filter, and side effects

Debugging WordPress can be difficult.  That’s an understatement.  I’m sure WordPress is not unique in this difficulty, because as software systems develop and increase in complexity, layers of abstraction increase, and larger and larger parts are like black holes.  The developer doesn’t really know what’s going on, doesn’t really want to spend hours digging through the black hole, so she stops the code at key execution points to see what’s going on, to look inside of variables, to prove that the code actually stepped through those lines…

But what do you do when you can see with the debugger that the code is executing but nothing appears on the screen?   This sounds like it could be a good interview question about debugging.

The lesson I’ve learned today, is don’t be afraid of looking at a call stack!  It should be your first, not last, go-to clue.  Generate a call stack, dig through it, and get to the bottom of it…

This will give you a call stack as an associative array:

$my_callstack = debug_backtrace();

Or you could trigger an error which will give you a stack call if you have Xdebug turned on.

So, really, how could code execute but not appear on the screen?

We’re going to assume that it’s not a CSS display:none attribute or javascript removing an HTML node.  We’re going to address a pure PHP cause for code to appear executed but yet not appear on the screen.  And this is not something simple like forgetting to echo.  (Yeah, check that you echoed that statement!  Maybe the function you are calling returns the data instead of outputting it?)

One PHP cause could be that output buffering is turned on.  Which is something you would easily see in a call stack.

But a more likely WordPress cause is that the code is attached to a filter or a hook and is being called in a different context than you expected.

In today’s bug, I had attached a callable function to the_content filter.  The function I attached altered a variable that was used to keep track of some data (to be precise, it was storing post_ids to prevent their re-use).

I thought that the_content filter was only called when the_content() function was called, so I thought it would only be called once with each page load.  But using Xdebug and PhpStorm to step through the code, it was evident that my function was being called 5 times with each page load! This was causing huge logic (and data) errors, not to mention performance issues.  These errors were hard to reproduce so it created bugs that would pop up randomly.  So I googled phrases like “wordpress the_content filter being called multiple times”.

But, Google wasn’t any help.  The more I learn about any given topic, the less helpful Google results become.

I guess that makes sense.

Anyway, I found out that a Jetpack plugin was calling wp_trim_excerpt, which applies the_content filter and my code was executing but not appearing on the screen, because, in a sense, the_content’s context was related to the post excerpt.  Wow, that’s a mouthful!  So lesson learned, the_context gets filtered when you’re doing stuff with the_excerpt.

I don’t even know what Jetpack was doing with that code.  But in any case, my code was running at the wrong time, because of how WordPress works.  The context was wrong in 2 ways.  First, the plugin, and not my theme, was causing my code to run.  And second, it was working with the excerpt, not the content.   Now, the first fact, is often desirable.  You inject code with filters and action hooks because you want your code to effect WordPress core, and other WordPress themes and plugins that you didn’t write.  Yeah, kind of like spaghetti code, right?  But being able to modify other code is crucial to how WordPress works… So what makes it great also makes it difficult.  Sounds kind of like Ruby Gems?  Intertwine enough stuff and something is going to go haywire.

So, how many other plugins call functions that deal with a post excerpt or post content which causes the_content filter to run?  Probably pretty common stuff.

Be Really Careful with using the_content filter for anything that might have side effects

The Solution

function do_something_special_with_content() {
    add_filter('the_content', 'my_special_function', 10);
    the_content();
    remove_filter('the_content', 'my_special_function', 10);
}

my_special_function( $content ) {
   // do something
   return $content;
}

If you write the code that way, you’ve limited the scope of when your function will run.  That’s the goal, right?

I don’t think WordPress Core really uses “context” as a programming concept, but you’ll see the idea of a context come up often in other frameworks.  (I’m looking at you, Android.)  It helps with figuring out what should be done when. Maybe WordPress needs contexts.  Or maybe that would just make it even more confusing…

Off to more WordPress adventures.

More on Debugging WordPress

Debugging in WordPress – WP_DEBUG, WP_DEBUG_LOG, and more.

 

Leave a Reply

Your email address will not be published. Required fields are marked *

*