如何编写PHP代码来用__invoke()
调用所有"Callables"?
此处的愿望是通过引用传递的,call_user_func[_array]()
不赞成使用该引用。我确实看到有一个包,TRex'Reflection'CallableReflection
,但这似乎在后台使用了call_user_func()
,并且会遇到同样的问题。
<?php
function passthrough_invoke(callable $callback) {
return $callback->__invoke();
}
function passthrough_user(callable $callback) {
return call_user_func($callback);
}
function test_func() { return "func_string'n"; };
class test_obj {
function test_method() {
return "obj_method'n";
}
}
print_r("Call User Func Works:'n");
echo passthrough_user(function() { return "func_closure'n"; });
echo passthrough_user(array(new test_obj, 'test_method'));
echo passthrough_user('test_func');
print_r("'n__invoke dies:'n");
echo passthrough_invoke(function() { return "func_closure'n"; });
echo passthrough_invoke(array(new test_obj, 'test_method'));
echo passthrough_invoke('test_func');
这个问题也可能是"有没有一种方法不会被否决,你可以通过引用调用回调?",但我觉得当前的问题更有趣。
注意:
主要目标是让回调充当一个完整的函数,并具有它的所有细节,主要包括__invoke($args, ...)
允许的Pass By Reference。
使用func_get_args()
或...$args
(包装器上的可变函数)将不起作用,因为您仍将使用call_user_func_array($callback, $arg_array)
,它将不支持传递引用。
注释2:
我刚刚了解到,在下一个PHP:function_name(...$args)
中,您也可以使用可变参数进行CALL。此支持是否通过引用?
此外,我们仍然遇到$callback_array = array($object, 'method');
是可调用的问题,但$callback_array();
不可调用,当然$callback_array(...$args);
也不可调用。此外,我应该澄清的是,这个问题实际上是关于编写在以后的版本中不会中断的代码。
IE:我现在可以写,明天运行。
这看起来前景越来越黯淡。
调用类成员很容易实现:
<?php
function passthrough_invoke(callable $callback) {
return $callback->__invoke();
}
function passthrough_user(callable $callback) {
return call_user_func($callback);
}
function test_func() { return "func_string'n"; };
class test_obj {
public function test_method() {
return "obj_method'n";
}
}
class CallableWrapper {
private $inst, $meth;
public function __construct( $inst, $meth ) {
$this->inst = $inst;
$this->meth = $meth;
}
public function __invoke() {
echo $this->inst->{$this->meth}();
}
}
print_r("Call User Func Works:'n");
echo passthrough_user(function() { return "func_closure'n"; });
echo passthrough_user(array(new test_obj, 'test_method'));
echo passthrough_user('test_func');
print_r("'n__invoke rocks:'n");
echo passthrough_invoke( function() { return "func_closure'n"; } );
echo passthrough_invoke(
new CallableWrapper( new test_obj, 'test_method' )
);
// ⇒
// __invoke rocks:
// func_closure
// obj_method
对于全局范围的函数,它也应该是可行的,但我拒绝尝试实现错误的模式:)