They are very hard if not impossible to unhook.

While both closures and anonymous functions are anonymous and can capture variables from the surrounding scope, closures have additional capabilities related to variable scope and lifetime management; however, in common use, the term “closure” is often used to refer to any anonymous function, leading to the confusion between the two terms.

Callback Info is currently only available on GitHub. At the time of this writing, it’s in the pending queue for the WordPress Plugin Repository.


Periodically, PHP will run an internal mechanism looking for values in memory that are no longer needed and free up the memory.

When I first started writing about anonymous functions in WordPress back in January, I didn’t anticipate it spanning over three articles reaching into the fourth month of the year. But here we are.

This is where PHP’s Reflection classes come in handy.

This is where we can start making headway in locating anonymous functions and how we can manage them. Further, we can even determine what kind of function is being registered with a given hook.

That said, this final article in the series aims to help provide a short introduction to a number of technical ideas both in PHP and WordPress to explain why deregistering anonymous functions is nearly impossible.

Deregister Anonymous Functions in WordPress

This is not what it means to remove a function from a hook.

By that, I mean we can determine if the associated functions are object-based functions, static functions, functions part of the global namespace, or even anonymous functions.

In short, perhaps it’s easy to remember it by saying “all closures are anonymous functions but not all anonymous functions are closures.”

A Brief Summary of Anonymous Functions in WordPress

In the next article, I’ll walk through a process – regardless of how manual it is – for how to deregister the functions.

  1. Anonymous functions (also called closures in PHP) are useful when you have a small, one-time callback that doesn’t need to be referenced elsewhere in your code.
  2. When an anonymous function is registered with a WordPress hook, PHP generates a unique ID for the closure using the spl_object_hash() function, and associates this ID with the callback function.
  3. This allows WordPress to track and manage callbacks even when they are anonymous functions.
  4. I show how to get the closure ID generated by PHP for a specific anonymous function callback.
  5. I talk about the global $wp_filter object and explain how it holds information on all registered actions and filters in WordPress.
  6. I share information for how to easily list all functions/callbacks hooked to a specific hook like wp_enqueue_scripts.
  7. I provide an example for how to create your own anonymous function hooked to wp_enqueue_scripts for testing purposes.
  8. The debug_backtrace() PHP function is used to render information about the call stack, including the object representing the anonymous function.
  9. Through the debug_backtrace() function, I show how to obtain the internal ID generated by PHP for a given anonymous function that’s registered with a specific hook.

And that’s what I intend to do in this article. Further, I’ll share a utility that I’ve written that helps give context to each function – anonymous or not – and where it’s located within the instance of WordPress where it’s running

The behavior of unset() inside of a function can vary depending on what type of variable you are attempting to destroy.
How To Identify Anonymous Functions in WordPress

I do wish developers would stop using WordPress hooks with (what I think are called) anonymous functions […].

A Brief Survey of Technical Details

There is more information about using the callback information as well as the sample anonymous function included with the plugin.

Is this how you picture anonymous functions?

Closures and Anonymous Functions

Though I obviously recommend reading those articles (1, 2), here is a brief summary of what’s covered between the two of them:

In other words, we can use PHP to iterate through all of the hooks that exist in an instance of WordPress, all of the functions and their types that exist in the installation, and even what file and where the functions are located within the file.

  • A closure is a special type of anonymous function that has access to variables from the outer scope even after the outer function has returned. It’s like having a function within a function and the inner function has access to the variables in the function that contains it.
  • An anonymous function is a general term for any function defined without a name. In PHP, anonymous functions can be used just like named functions, but they are typically used as callback functions or for short, one-off tasks.

And given that:

  • Both are defined without a name, hence the term “anonymous.” They are typically used when you need a small, one-time-use function without the need to give it a specific name.
  • Both can access variables from the enclosing scope through variable capturing. This means they can “close over” variables and maintain their values even after the enclosing function has finished executing.

Consider the definitions of each:

This will render all of the hooks along with each function that fires during that hook. Further, you’ll see which file in which the function belongs as well as the starting line number and ending line number for the callback.

So when discussing anonymous functions in the context of WordPress hooks, it’s absolutely more accurate to state ‘anonymous functions.’

Garbage Collection in PHP

Collecting garbage computers is not the same as garbage collection in a computer.

In the course of the three articles that have covered a variety of topics from how anonymous functions are managed within WordPress and PHP, how to get contextual information about each of them, and how we can use built-in PHP functions to get as much contextual information about them.

What are we to do?

Recall from the first article, the reason I started writing about anonymous functions in WordPress all stemmed from a tweet (or post or whatever they are currently called) that stated:

This is important as it relates to trying to manually clear values registered with WordPress. Whenever an anonymous function is registered with a WordPress hook, the function will be given an ID that’s maintained by PHP internals. WordPress will also track a reference to the same function using the discussed $wp_filter object.

And finally, all of this resulted in a plugin that I hope helps developers achieve all of the above as easily as possible. I do have a roadmap of ideas for Callback Info but it’s contingent on how well it’s received or deemed useful by those who use it.

This gives you the ability to manipulate the functions as you see fit. Even if it means locating an anonymous function, naming it, and then deregistering it (or allowing it to be deregistered through the use of other core functionality).

Given this, it’s possible to iterate through the data structures maintained by the $wp_filter object and it’s even possible to call PHP’s unset on the value referenced by the $wp_filter object leading one of think that it may be possible to brute force the process of deregistering a function.
unset, via the PHP Manual

If a globalized variable is unset() inside of a function, only the local variable is destroyed. The variable in the calling environment will retain the same value as before unset() was called.

So it’s possible to unset a reference but the associated function may not actually be deregistered with WordPress until the garbage collector runs. And since it runs non-deterministically, we can never really know if the function is still in memory.

Through the use of Reflection and an understanding of the aforementioned function types, it’s possible to get a lot of contextual information about every single type of function registered with every single WordPress hook in the instance of WordPress you’re running.

A Short Introduction to Reflection

If we could personify reflection of our code, it’d look like this. Maybe.

And it provides a way for us to actually get contextual information about every single hook and callback in an instance of WordPress so we can handle the anonymous functions as we see fit all through the use of a plugin.

They are similar in the following ways:
Reflection via the PHP Manual

But it’s not impossible.

Ultimately, this allows us to actually manually deregister anonymous functions.

  • object-based functions are functions that are associated with an object,
  • static functions are functions that belong to a class rather than to instances of the class,
  • global functions are accessible from anywhere within PHP,
  • anonymous function are functions without a specified name and are often created as a callback.

PHP comes with a complete reflection API that adds the ability to introspect classes, interfaces, functions, methods and extensions. Additionally, the reflection API offers ways to retrieve doc comments for functions, classes and methods.

This plugin renders contextual information about every function registered with all WordPress hooks.

I wrote a small utility to help provide contextual information about every function registered with all WordPress hooks.

All of the above helps to get a step closer to writing – or working with – code that can be more maintainable, communicating with developers to make it more so, or to get more contextual information about the environment in which all of our code is running.

Callback Info, a WordPress Plugin

When working through the first two articles of this series, I wrote sample code that I shared throughout each of the blog posts. And the more work I did and the more I researched to put content into all of these articles, I more I was writing small utilities in my local development environment.

Callback Info looks at each hook used in the current WordPress instance including the active themes and plugins and renders:

  • we can easily get contextual information about all of the types of functions and to which hook they are registered in WordPress,
  • and there is a need for others to locate and alter these functions so they can deregister them (or at least reach out to the developers maintaining the software so they can refactor them),

And at the end of the second article, I wrote:

Though you can skip to the end of the article to see the practical aspect of locating anonymous functions and deregistering them, there are technical concepts worth reviewing that are helpful in understanding why dealing with anonymous functions are problematic and the strategies we can use to locate them.

And the short of it is that it’s true: Anonymous functions are easy to register against WordPress hooks and are difficult to deregister.

Callback Info

If you’ve stumbled across this article, here’s this is what the first two articles covered (should you be interested in reading them):

It also has a sample anonymous function that you can manually invoke so you can trace it in the data that you see above and then see how to use the data to locate and manipulate the function as you see fit.

Assuming that your domain is https://plugin.test, append the query string ?show-callback-info=true to your URL such that the address is https://plugin.test?show-callback-info=true.

What The Plugin Does

Specifically, the plugin iterates through each hook and lists the type of callback function (object, static, global, or anonymous), and where it’s located:

  • the name of the hook,
  • the type of method (object, static, standard function, or anonymous),
  • the file in which it’s registered,
  • the line on which the function starts,
  • the line on which the function ends.

And since WordPress plugins, themes, core, and associated tools are open source, we can refactor the ways in which prove useful to us, it allows us to modify the code, open issues with theme or plugin authors, and more.

Usage Instructions

There’s catch, though: The garbage collector. More specifically, when we destroy a specific variable maintained in $wp_filter, we are at the mercy of the garbage collector.

unset() destroys the specified variables.

And More

If you’re comfortable downloading and installing plugins from GitHub then head to the releases page and the first release of the plugin. It’s extremely important to read the README if for not other reason that these two parts:

In the latter, I provided some examples for how to programmatically identify the anonymous functions that exist in the instance of WordPress in which said code is running. Further, I provided an example function to include in the code so you can easily trace what the aforementioned code was doing.

Conclusion

I’ll also have additional information about this plugin in the next few weeks.

The terms ‘anonymous functions’ and ‘closures’ are often used interchangeably in WordPress. Though they are similar, there are also differences worth noting.

When variables or objects are created in PHP, memory is allocated to store their values; however, when these variables or objects are no longer needed, they occupy memory space unnecessarily. Because of that, these values are referred to as garbage.

Similar Posts