Tired of whatever silly color I've picked? Rotate the overall hue by hovering the site title!

Be wary when footer debugging

I know you're not "supposed" to debug things by outputting them into or past the footer of a site, but sometimes you just need to check on something real quick, like the ID or some other bit of data about a post, and you don't feel like dealing with any proper debugging tools. The wp_footer hook then gets used and the results don't make sense. What happened?

Inside The Loop™ of some template, you add the first bit of code. The values you see aren't correct, though, so you adjust it to the second bit of code.

add_action('wp_footer', function () {
	var_dump(get_the_ID());
});
$pid = get_the_ID();

add_action('wp_footer', function () use ($pid) {
    var_dump($pid);
});

Both of these output their values at the same time, on the wp_footer hook, but the values they output differ. You had a loop of three posts (IDs 1, 2, and 3 for simplicity) but something odd is afoot in your footer.

// The first outputs:
3 3 3

// The second outputs:
1 2 3

What gives? The two bits of code appear to be doing the same thing, outputting the current loop'd post's ID, but there's an important difference in the scoping. One calls get_the_ID() directly within the wp_footer hook while the other sets its value to a variable beforehand and then sticks it into a closure.

Aside: Closures in PHP are different from closures in JS. Because nothing is allowed to be simple. A closure in JS is a function bound to its scope and the variables within. A closure in PHP is written as an anonymous function, but it's actually a callable class whose parameters you set manually on creation.

There's a subtle and important difference in the timing, and I'm sure there's a name for it, but it's been a long time since I was fussing with college and knew the terms for such things. I am but a lowly idiot in the end.

  • The first bit of code isn't executing get_the_ID() until much later, well after the query and loop, and as such it will output the ID of the last post in the query. Not only that, but if the query reset the global WP variables after it was done, you'll instead get the ID of the page itself and not the IDs of any of the posts. It's two layers of wrong!
  • The second bit of code is executing get_the_ID() immediately, within the loop, and as such it's grabbing the expected value. That value is then bound to the closure on its creation, ensuring that despite the code running well after the query and loop, the value you've passed in (by copy) is locked in.

Is this more proof that you shouldn't debug in your footer? Yeah, probably. But there's a deeper concern about the timing of when a function is actually called. The first bit of code above makes sense at first glance, but that function call to get an ID is actually happening way later than you'd intended.

If you're going to debug in such a simple way ⸺ output a thing and see what you get ⸺ then you should use a different method. You can, for instance, send it to the browser's console instead. This will not only prevent any ugly output from showing on the site, but you won't run into timing issues!

function log_me_baby($thing) {
    printf('<script>console.log(%s)</script>', json_encode($thing));
}

You'll perhaps want to rewrite this to do some extra checks and handle any number of parameters, but this'll get you started.

Leave a comment

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