2014-11-06 1 views
2

Как написать PHP-код для вызова всех «Callables» с помощью __invoke()?__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'); 

Этот вопрос может также лунный свет, как «Есть ли способ, что не собирается быть устаревшим, что вы можете вызвать функцию обратного вызова с выведенным по ссылке?», Но я считаю, текущий вопрос более интересным.

Примечание:

Основная цель состоит в том, чтобы иметь обратный вызов выступать в качестве полной функции, и есть все тонкости, которые, в первую очередь в том числе передачи по ссылке, которая __invoke($args, ...) позволяет.

с помощью func_get_args() или ...$args (VARIADIC функции на обертке) не будет работать, так как вы все равно останетесь с использованием call_user_func_array($callback, $arg_array), который не будет поддерживать передачу по ссылке.

Примечание 2:

Я только что узнал, что вы можете вызвать с помощью VARIADIC параметров, а в следующий PHP: function_name(...$args). Проходит ли эта поддержка по ссылке?

Далее мы до сих пор сталкиваемся с вопросом, что $callback_array = array($object, 'method'); является вызываемым, но не $callback_array();, и, конечно же, не $callback_array(...$args);. Далее, я должен уточнить, что на самом деле вопрос заключается в написании кода, который не будет ломаться в более поздних версиях, которые могут это сделать.

IE: Я могу написать его сейчас, запустить его завтра.

Какой выглядит диммер и диммер перспективы.

+0

«проходят по ссылке, который устарел с помощью call_user_func [_array]() " Это не совсем так. * Call-time * pass-by-reference устарела в 5.3 и удалена в 5.4 для всех функций. Тем не менее, вы все равно можете использовать 'call_user_func_array' для передачи аргументов по ссылке на функцию, которая принимала эти аргументы по ссылке, путем размещения ссылок в массиве, потому что это не пропускная способность по времени вызова. Вместо этого ваша проблема заключается в том, что вы не можете * получить * аргументы, переданные по ссылке (и сохранить ее как ссылку) в вариационной функции. – newacct

+0

Я знал это в какой-то момент, но я подумал, что я читал, что это тоже было устаревшим. Я смотрю на это сейчас ...:// – Mike

ответ

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 

Для глобальных контекстных функций должна быть выполнимы, а также, но я отказываюсь, чтобы попытаться реализовать неправильные модели :)

+0

Что вы считаете «плохой практикой» о том, что, по вашему мнению, выполнимо? – Mike

+0

Это не дает возможности передать переменные вызываемому. : -/Sad, я получил возбуждение ... – Mike

+0

Можно передать третий параметр для вызова конструктора 'CallableWrapper' и использовать его в вызове' __invoke'. – mudasobwa