Search code examples
phpwordpresscall-user-func-array

Passing a class, method and arguments to WordPress functions


When adding pages to the WordPress admin you use add_menu_page, which accepts a callable function/method.

class Foo
{
    public function __construct()
    {
        add_menu_page($page_title, $menu_title, $capability, $menu_slug, [$this, 'bar'], $icon_url, $position);
    }

    public function bar(): void
    {
        echo 'Hello, World!';
    }
}

My issue is, I'm a little stumped on how to pass an argument to bar when it accepts/expects parameters, for example:

class Foo
{
    public function __construct()
    {
        add_menu_page($page_title, $menu_title, $capability, $menu_slug, [$this, 'bar'], $icon_url, $position);
    }

    public function bar(string $name = ''): void
    {
        echo "Hello, {$name}!";
    }
}

I've tried a couple different approaches but I can't seem to get it to work:

[$this, 'bar', 'Bob']; // Warning: call_user_func_array() expects parameter 1 to be a valid callback, array must have exactly two members in /wp-includes/class-wp-hook.php on line 287

[$this, ['bar', 'Bob']] // Warning: call_user_func_array() expects parameter 1 to be a valid callback, second array member is not a valid method in /wp-includes/class-wp-hook.php on line 287

So looking at line 287 of that file, it's using call_user_func_array and I think it seems as if it's possible to pass an argument in the $function parameter of add_menu_page but I just cannot get it to work:

// Avoid the array_slice() if possible.
if ( 0 == $the_['accepted_args'] ) {
    $value = call_user_func( $the_['function'] );
} elseif ( $the_['accepted_args'] >= $num_args ) {
    $value = call_user_func_array( $the_['function'], $args );
} else {
    $value = call_user_func_array( $the_['function'], array_slice( $args, 0, (int) $the_['accepted_args'] ) );
}

Help would be appreciated!


Solution

  • You should be able to pass an anonymous function instead, whose body would simply call the bar method with the appropriate arguments.

    The anonymous function would look like this:

    function () { $this->bar('Bob'); }
    

    Or alternatively, if you're using PHP 7.4+:

    fn() => $this->bar('Bob')
    

    So, just pass that as the callback, like this:

    add_menu_page(
      $page_title,
      $menu_title,
      $capability,
      $menu_slug,
      // fn() => $this->bar('Bob'),
      function () {  
        $this->bar('Bob');  
      },
      $icon_url,
      $position
    );
    

    Note: I'm very unfamiliar with WordPress so this might not be the most appropriate way to do this.