Skip to content

Debugging WordPress Filters with Xdebug

Published on

Have you ever had a filter produce output that bewildered you and you weren’t sure how that output was being generated? I’d like to show you how using Xdebug can make that job a little easier.

One of the first things that may come to your mind is What about Debug Bar/Query Monitor? Those plugins are great and I definitely advocate for having those in your toolbelt! An instance where they might not help too much is if an action/filter has been added as a closure/anonymous function, then those tools can’t display where that function was loaded from:


Sure, you can search your codebase for functions that modify the filter. That’s certainly one way to solve the problem. Another is to leverage Xdebug’s ability to step through an application and see what’s loaded and how inputs are modified. By setting breakpoints at specific portions of the code, we’re able to see how a filter is being applied as well as which functions are modifying the input. For instance: let’s say our post permalinks are being modified and we’re not sure why or what exactly is doing the modifications. Xdebug allows us to gain a deeper visibility into the code!

First, let’s narrow down what may be causing the problem. There are three primary filters used for modifying post permalinks: the_permalink, pre_post_link, and post_link (pages, attachments, and custom post types have an extra filter dedicated for each type). By opening up our handy-dandy Debug Bar and using the Actions and Filters addon, we can see there’s a function hooked into the post_link filter:

post_link filter

Unfortunately, we can’t see where that function is defined from here, so let’s have a look-see via Xdebug! What I’m going to do is add a function to a mu-plugin to fast-track me to the post_link filter:

// @ mu-plugins/xdebug.php
add_filter('post_link', function($permalink, $post, $leavename) {
    return $permalink;
}, 0, 3);

As we’re not sure which function is modifying the permalink, we insert a Breakpoint at the very beginning of the filter chain processing the post_link filter by setting priority 0. If you wanted, you could even add it as a negative number in the event there are filters registered at priority 0. It’s important to return $permalink because otherwise, the filters further down the chain wouldn’t have anything to filter!

Then, with our debugger enabled and Xdebug configured properly to connect to the debugger, we load the page in a browser to kick Xdebug off. Once you’ve progressed through the application to this breakpoint, you can Step Out of the function into the apply_filters function:


This will land you on line 275 of wp-includes/class-wp-filter, which at the time of this writing is WordPress 4.9.7. Now that you’re within the apply_filters function, you can step through each of the functions that are registered to the post_link filter (those functions are called via the calls to call_user_func_array here).

About the author

Nathaniel Schweinberg

Nathaniel is a Systems Engineer responsible for automating server infrastructure, making sure it stays available, and authoring software to support these tasks. When he’s not working, you can find Nathaniel spending time with his friends around a board game or off on a hike in the hills of Vacaville, CA.