I am trying to store a callable/closure as a class field/property.
My initial attempt was this:
class MyClass
{
protected callable $modifier;
public function __construct(callable $modifier) {
$this->modifier = $modifier;
}
}
class SomeOtherClass
{
public static function func()
{
return ['a' => 'b'];
}
}
$test = new MyClass('SomeOtherClass::func');
This returned an error of:
$modifier cannot have type callable
Then, after reading this online, I’ve tried this with no success:
class MyClass
{
protected Closure $modifier;
public function __construct(callable $modifier) {
$this->modifier = Closure::fromCallable($modifier);
}
}
class SomeOtherClass
{
public static function func()
{
return ['a' => 'b'];
}
}
$test = new MyClass('SomeOtherClass::func');
This last one returns this error:
Argument #1 ($modifier) must be of type callable, string given
Then I’ve tried this:
class MyClass
{
protected Closure $modifier;
public function __construct(callable $modifier) {
$this->modifier = Closure::fromCallable($modifier);
}
}
class SomeOtherClass
{
public static function func()
{
return ['a' => 'b'];
}
}
$test = new MyClass(['SomeOtherClass', 'func']); // <----- changed string to an array
Which returns this error:
Argument #1 ($modifier) must be of type callable, array given
Is this even possible to do in PHP?
2
Answers
Assuming you’re using PHP 8.1 or above (which at the time of writing are the only supported versions of PHP anyway), then you can use first-class callable syntax, as introduced in 8.1.
To do this, you use the name of a function and then
(...)
as the argument to pass in.In your case, you could therefore do this:
Live demo: https://3v4l.org/nMmvq
N.B. The code above assumes that you want to use
func()
as a static method (as defined in your sample code). If anyone is reading and wants to do something similar but with an instance method, you’d need a small adjustment as follows:Live demo: https://3v4l.org/iEAiM
Just for the sake of completeness. The problem in OP’s code was most likely caused by namespaces.
You have to use fully qualified name in array/string callable. So, you have to use
[SomeOtherClass::class, 'func']
or['MyNamespaceSomeOtherClass', 'func']
.See live demo: https://3v4l.org/pnWYC