Ken*_*ins 100 php closures properties object
我希望能够直接调用我分配给对象属性的闭包,而无需将闭包重新分配给变量然后调用它.这可能吗?
下面的代码不起作用和原因Fatal error: Call to undefined method stdClass::callback()
.
$obj = new stdClass();
$obj->callback = function() {
print "HelloWorld!";
};
$obj->callback();
Run Code Online (Sandbox Code Playgroud)
Bri*_*and 101
你可以通过在闭包上调用__invoke来做到这一点,因为这是对象用来表现像函数的神奇方法:
$obj = new stdClass();
$obj->callback = function() {
print "HelloWorld!";
};
$obj->callback->__invoke();
Run Code Online (Sandbox Code Playgroud)
当然,如果回调是一个数组或一个字符串(在PHP中也可以是有效的回调),这将无效 - 只是对于具有__invoke行为的闭包和其他对象.
Gor*_*don 96
从PHP7开始,你可以做到
$obj = new StdClass;
$obj->fn = function($arg) { return "Hello $arg"; };
echo ($obj->fn)('World');
Run Code Online (Sandbox Code Playgroud)
或者使用Closure :: call(),虽然这对a不起作用StdClass
.
在PHP7之前,你必须实现魔术__call
方法来拦截调用并调用回调(StdClass
当然这是不可能的,因为你不能添加__call
方法)
class Foo
{
public function __call($method, $args)
{
if(is_callable(array($this, $method))) {
return call_user_func_array($this->$method, $args);
}
// else throw exception
}
}
$foo = new Foo;
$foo->cb = function($who) { return "Hello $who"; };
echo $foo->cb('World');
Run Code Online (Sandbox Code Playgroud)
请注意,你做不到
return call_user_func_array(array($this, $method), $args);
Run Code Online (Sandbox Code Playgroud)
在__call
体内,因为这会__call
在无限循环中触发.
似乎可以使用call_user_func()
.
call_user_func($obj->callback);
Run Code Online (Sandbox Code Playgroud)
虽然不优雅,但@Gordon所说的可能是唯一可行的方法.
好吧,如果你真的坚持.另一个解决方法是:
$obj = new ArrayObject(array(),2);
$obj->callback = function() {
print "HelloWorld!";
};
$obj['callback']();
Run Code Online (Sandbox Code Playgroud)
但这不是最好的语法.
然而,PHP解析器始终将T_OBJECT_OPERATOR
,IDENTIFIER
,(
如方法调用.似乎没有办法->
绕过方法表并访问属性.
我知道这是旧的,但我认为Traits很好地处理这个问题,如果你使用PHP 5.4+
首先,创建一个使属性可调用的特征:
trait CallableProperty {
public function __call($method, $args) {
if (property_exists($this, $method) && is_callable($this->$method)) {
return call_user_func_array($this->$method, $args);
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以在您的类中使用该特征:
class CallableStdClass extends stdClass {
use CallableProperty;
}
Run Code Online (Sandbox Code Playgroud)
现在,您可以通过匿名函数定义属性并直接调用它们:
$foo = new CallableStdClass();
$foo->add = function ($a, $b) { return $a + $b; };
$foo->add(2, 2); // 4
Run Code Online (Sandbox Code Playgroud)
$obj->callback->call($obj);
Run Code Online (Sandbox Code Playgroud)
由于PHP 7也可以对任意(...)
表达式执行操作(如Korikulum所述):
($obj->callback)();
Run Code Online (Sandbox Code Playgroud)
其他常见的PHP 5方法是:
使用魔术方法__invoke()
(由Brilliand解释)
$obj->callback->__invoke();
Run Code Online (Sandbox Code Playgroud)使用该call_user_func()
功能
call_user_func($obj->callback);
Run Code Online (Sandbox Code Playgroud)在表达式中使用中间变量
($_ = $obj->callback) && $_();
Run Code Online (Sandbox Code Playgroud)每种方式都有自己的优点和缺点,但最激进和最终的解决方案仍然是戈登提出的解决方案.
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();
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
30414 次 |
最近记录: |