可调用数组或字符串上的__invoke()

时间:2014-11-06 16:27:52

标签: php reflection callback pass-by-reference invoke

如何编写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),这将不支持Pass By Reference。< / p>

备注2:

我刚刚了解到你可以在下一个PHP中使用可变参数进行调用:function_name(...$args)。这种支持是否通过引用传递?

此外,我们仍然遇到$callback_array = array($object, 'method');可以调用但不是$callback_array();,而不是$callback_array(...$args);的问题。此外,我应该澄清,问题实际上是关于编写代码,这些代码在以后的版本中不会破坏,可以做到这一点。

IE:我现在可以写了,明天运行。

对于潜在客户来说,这看起来越来越暗淡。

1 个答案:

答案 0 :(得分:0)

调用类成员很容易实现:

<?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

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