WordPress core is about to raise minimum PHP requirement to version 5.6. That brings a wider access to cutting–edge nine years old features, such as anonymous functions (aka closures).
Closures had immediately generates some push back against using them with WordPress hooks. That is where they can shine though!
Inline callbacks
Closure in PHP is a callable. You can use closure like any other callable. Both simpler (functions) and more complex (invokable classes).
In WordPress the common use of callable is a hook callback:
add_filter( 'answer', function () {
return 42;
} );
So closure can be a quick way to write a callback inline. Closures have many more uses, such as strategies and lazy service definitions.
Scope inheritance
A trivial function callback will only have access to its argument. And a global scope, which is a bad idea.
Closure has another way — it can inherit from parent scope:
foreach ( [ 32, 42, 52 ] as $answer ) {
add_filter( "answer_{$answer}", function () use ( $answer ) {
return $answer;
} );
}
This will create three different callbacks from one definition. Technically anonymous function is a Closure instance. So every time we create a new instance and it can inherit what we want from the current scope.
This is very powerful way to build elaborate callbacks that combine logic with data.
Object binding
Wait, if a closure is an object, does it have $this ? Not a random question. A closure defined inside a class binds to the object’s context so $this refers to the object, not closure itself:
class Answer {
private $answer = 42;
public function __construct() {
add_filter( 'answer', function () {
return $this->answer;
} );
}
}
This is also a very powerful feature. We can build complex callbacks with access to object’s private methods and properties without exposing them as public API.
Removing from hooks
And here is the downside. In WordPress to remove an object–based callback from a hook you need access to the original instance. Without it there is no way to communicate to API which callback you want to be removed.
With closures this can be a challenge. More so when interacting with callbacks from code that is not your own.
But it is shortsighted to consider this downside of a closure! It is much more of a shortcoming on the side of WordPress core.
If you worry about this aspect there are both solid materials on removing closures and a ticket to improve this in WordPress core.
Overall
Anonymous function is a powerful PHP feature. It can be used to build both trivial and elaborate callbacks. Closures have unique abilities to inherit from parent scope and access the object where they were defined.
In WordPress context you don’t want to use closures excessively for hook callbacks, due to current API limitations.
But don’t hesitate to explore them for complex use cases! The benefits of closure outweigh the downsides.
Slava Abakumov #
Andrey “Rarst” Savchenko #
Slava Abakumov #