__invoke() on callable Array or String


__invoke() on callable Array or String

如何编写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

对于全局范围的函数,它也应该是可行的,但我拒绝尝试实现错误的模式:)