3

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!

no.
  • 2,356
  • 3
  • 27
  • 42

1 Answers1

3

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.

Jeto
  • 14,596
  • 2
  • 32
  • 46
  • 1
    Perfect, I didn't even think of just passing a callback directly through it like that. I can't see why it would be inappropriate either, as all it is expecting is a callable function, which this is. I just didn't realize `$this` would be available within in the anonymous function. Thanks! – no. Aug 05 '20 at 11:32