2

I have some code that executes an anonymous function that, which looks something like this

class A
{
    public static function foo(callable $callback)
    {
        $callback('Foo executed.');
    }
}

class B
{
    public function execute()
    {
        A::foo(function ($phrase) {
            echo $phrase;
        });
    }
}

$b = new B();
$b->execute();  // "Foo executed."

but instead of doing it that way, I want to move the anonymous function to be a class method and then pass that method as the parameter.

The problem is that I am not sure how or if it's even possible to reference the class method in this manner when doing it with a custom method.

Basically, I want to be able to reference the function without calling it, similar to how you can do array_map('strtoupper', $words) with native PHP functions, referencing the native strtoupper method instead of doing function ($w) { return strtoupper($w); }.

Here is what I would prefer to do:

class A
{
    public static function foo(callable $callback)
    {
        $callback('Foo executed');
    }
}

class B
{
    public function execute()
    {
        A::foo('speak');  // <- This is obviously wrong because we are passing a string and not a callable
    }

    public function speak($phrase)
    {
        echo $phrase;
    }
}

I've also tried doing, but they result in the respective errors:

  • static::speak results in Undefined class constant 'speak'
  • $this::speak results in Undefined class constant 'speak'
  • self::speak results in Undefined class constant 'speak'
  • $this->speak results in Undefined property: B::$speak
  • $this->speak() results in Too few arguments to function B::speak(), 0 passed ...

How can I achieve this and is it even achievable in PHP?

Graham S.
  • 1,480
  • 1
  • 20
  • 28
  • Btw, my solution ended up being `A::(\Closure::fromCallable([$this, 'speak']))` because the type-hint was actually of type `Closure` in my case (Closure is stricter). For a normal `callable` type, you can simply pass `[$this, 'speak']` instead. I used the link to the duplicate question which led me to the solution I needed. – Graham S. Feb 11 '21 at 19:26

0 Answers0