I would like to be able to call a closure that I assign to an object\'s property directly without reassigning the closure to a variable and then calling it. Is this possible
I note that this works in PHP5.5
$a = array();
$a['callback'] = function() {
print "HelloWorld!";
};
$a['callback']();
Allows one to create a psuedo-object collection of closures.
You can do this by calling __invoke on the closure, since that's the magic method that objects use to behave like functions:
$obj = new stdClass();
$obj->callback = function() {
print "HelloWorld!";
};
$obj->callback->__invoke();
Of course that won't work if the callback is an array or a string (which can also be valid callbacks in PHP) - just for closures and other objects with __invoke behavior.
well, it should be emphisized that storing the closure in a variable, and call the varible is actually (wierdly) faster, depending on the call amount, it becomes quite a lot, with xdebug (so very precise measuring), we are talking about 1,5 (the factor, by using a varible, instead of directly calling the __invoke. so instead , just store the closure in a varible and call it.
Updated:
$obj = new stdClass();
$obj->callback = function() {
print "HelloWorld!";
};
PHP >= 7 :
($obj->callback)();
PHP >= 5.4 :
$callback = $obj->callback;
$callback();
It seems to be possible using call_user_func()
.
call_user_func($obj->callback);
not elegant, though.... What @Gordon says is probably the only way to go.
Since PHP 7 a closure can be called using the call() method:
$obj->callback->call($obj);
Since PHP 7 is possible to execute operations on arbitrary (...)
expressions too (as explained by Korikulum):
($obj->callback)();
Other common PHP 5 approaches are:
using the magic method __invoke() (as explained by Brilliand)
$obj->callback->__invoke();
using the call_user_func() function
call_user_func($obj->callback);
using an intermediate variable in an expression
($_ = $obj->callback) && $_();
Each way has its own pros and cons, but the most radical and definitive solution still remains the one presented by Gordon.
class stdKlass
{
public function __call($method, $arguments)
{
// is_callable([$this, $method])
// returns always true when __call() is defined.
// is_callable($this->$method)
// triggers a "PHP Notice: Undefined property" in case of missing property.
if (isset($this->$method) && is_callable($this->$method)) {
return call_user_func($this->$method, ...$arguments);
}
// throw exception
}
}
$obj = new stdKlass();
$obj->callback = function() { print "HelloWorld!"; };
$obj->callback();