Debugging WordPress Filters with Xdebug

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).

If I lost you at the point where I said "Xdebug configured properly," then don’t worry, we have you covered. We have a series covering Xdebug and configuring properly! If you’re interested in learning more about how to configure it for your development environment, how to use it with an IDE, or how to connect to a remote environment, check out our screencast series Debugging PHP with Xdebug: Beyond var_dump. We cover how to install and configure Xdebug with MAMP, Valet, and Trellis, as well as how to use Xdebug with Visual Studio Code and PHPStorm. Happy debugging!

Get the Screencast

Topics Covered

  • Introduction and Demo
  • Installing and Configuring XDebug
    • Trellis
    • Valet
    • MAMP
    • Choosing a Debugger/IDE: PHPStorm, VS Code, Sublime Text, or Vim?
    • Initiating a Debugging Session
    • Debugging Request Lifecycle explained
    • Configuring your IDE
      • Visual Studio Code
      • PHPStorm
    • Common features across debuggers
    • Getting to know your Debugger
      • Visual Studio Code
      • PHPStorm
    • Debugging Request Lifecycle explained
    • Using Xdebug remotely
    • Improving Xdebug’s `var_dump`

Preview & More Info

  • Length: 2+ hours
  • No DRM – H264, AAC, 1080p

Start the discussion on Roots Discourse

Help support our open-source development efforts

Help us grow

Join over 7,800+ subscribers on our newsletter to get the latest Roots updates, along with occasional tips on building better WordPress sites.

Looking for WordPress plugin recommendations, the newest modern WordPress projects, and general web development tips and articles?

“Easily the best WordPress email I get.” Colin OBrien

Follow us on Twitter @rootswp

Ready to checkout?