Anonymous functions in WordPress hooks

2019-02-05 21:51发布

问题:

WordPress hooks can be used in two ways:

  1. using callback function name and appropriate function

    add_action( 'action_name', 'callback_function_name' );
    function callback_function_name() {
        // do something
    }
    
  2. using anonymous function (closure)

    add_action( 'action_name', function() {
        // do something
    } );
    

Is there any difference for WordPress what way to use? What is prefered way and why?

回答1:

The disadvantage of the anonymous function is that you're not able to remove the action with remove_action.

Important: To remove a hook, the $function_to_remove and $priority arguments must match when the hook was added. This goes for both filters and actions. No warning will be given on removal failure.

Because you didn't define function_to_remove, you can't remove it.

So you should never use this inside plugins or themes that somebody else might want to overwrite.



回答2:

Using closures has the benefit of keeping the global namespace clean, because you don't have to create a global function first to pass as a callback.

add_action('admin_init', function () {
    // some code...
});

Personally I would prefer using closures as callbacks, unless:

  • You want the possibility of removing the callback
  • The callback function needs to be used more then once
  • You need support for older PHP versions (less then 5.3)

Closures in Classes

Closures can also be beneficial within classes.

class SomeClass
{
    public function __construct()
    {
        add_action('wp_head', function () {
            $this->addSomeStyling();
        });
    }

    protected function addSomeStyling()
    {
        echo '<style> body { color: #999; } </style>';
    }
}

Normally callback methods need to be made public, but in this case you can also make them private or protected.

This solution only works for PHP 5.4+. To also make it work for PHP 5.3, you need to explicitly pass the $this object reference to the closure, like:

    public function __construct()
    {
        $self = $this;

        add_action('wp_head', function () use ($self) {
            $self->addSomeStyling();
        });
    }