Как написать PHP-код для вызова всех «Callables» с __invoke()
?
Желание здесь передать по ссылке, которая устарела с 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');
Этот вопрос может также прозвучать так: «Есть ли способ, который не следует считать устаревшим, когда вы можете вызвать обратный вызов с передачей по ссылке?», Но я нахожу текущий вопрос более интересным.
Заметки:
Основная цель — сделать функцию обратного вызова полноценной функцией и иметь все тонкости этого, в том числе Pass By Reference, которая __invoke($args, ...)
позволяет.
с помощью func_get_args()
, или же ...$args
(переменная функция на обертке) не будет работать, так как вы все равно останетесь с помощью call_user_func_array($callback, $arg_array)
, который не будет поддерживать Pass By Reference.
Примечания 2:
Я только что узнал, что вы можете ВЫЗВАТЬ, используя переменные параметры, а также в следующем PHP: function_name(...$args)
, Эта поддержка передается по ссылке?
Далее мы все еще сталкиваемся с проблемой, которая $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
Для глобальной области видимости это также должно быть выполнимо, но я отказываюсь пытаться реализовать неправильные шаблоны 🙂
Других решений пока нет …