Подтвердить что ты не робот

Передача функции по ссылке в PHP

Можно ли передавать функции по ссылке?

Что-то вроде этого:

function call($func){
    $func();
}

function test(){
    echo "hello world!";
}

call(test);

Я знаю, что вы могли бы сделать 'test', но я этого действительно не хочу, поскольку мне нужно передать функцию по ссылке.

Это единственный способ сделать это через анонимные функции?

Уточнение: если вы помните из С++, вы можете передать функцию через указатели:

void call(void (*func)(void)){
    func();
}

Или в Python:

def call(func):
    func()

То, что я пытаюсь выполнить.

4b9b3361

Ответ 1

За что стоит, как насчет чего-то подобного? (Да, я знаю, что это анонимная функция, о которой упоминалось в сообщении, но я был недоволен множеством ответов, которые вообще не упоминали о закрытии/функциональных объектах, так что это в основном примечание для людей, работающих на этом посту.)

Я не использую PHP, но с использованием закрытия работает в PHP 5.3 (но не PHP 5.2) в качестве показанного здесь. Я не уверен, какие существуют ограничения, если таковые имеются. (Насколько я знаю, закрытие съест ваших детей. Вы были предупреждены.)

function doIt ($fn) {
  echo "doIt\n";
  return $fn();
}

function doMe () {
  echo "doMe\n";
}

// I am using a closure here.
// There may be a more clever way to "get the function-object" representing a given
// named function, but I do not know what it is. Again, I *don't use PHP* :-)
echo doIt(function () { doMe(); });

Счастливое кодирование.

Ответ 2

Проблема с call_user_func() заключается в том, что вы передаете возвращаемое значение вызываемой функции, а не самой функции.

Я тоже сталкивался с этой проблемой, и вот решение, с которым я столкнулся.

function funcRef($func){
  return create_function('', "return call_user_func_array('{$func}', func_get_args());");
}

function foo($a, $b, $c){
    return sprintf("A:%s B:%s C:%s", $a, $b, $c);
}

$b = funcRef("foo");

echo $b("hello", "world", 123);

//=> A:hello B:world C:123

демонстрация ideone.com

Ответ 3

function func1(){
    echo 'echo1 ';
    return 'return1';
}

function func2($func){
    echo 'echo2 ' . $func();
}

func2('func1');

Результат:

echo1 echo2 return1

Ответ 4

Нет, функции не являются значениями первого класса в PHP, они не могут быть переданы их литералом имени (это то, о чем вы просите). Даже анонимные функции или функции, созданные с помощью create_function, передаются ссылкой на объект или строку.

Вы можете передать имя функции как строку, имя объекта-объекта как массив (object, string) или анонимную функцию как объект. Ни один из этих указателей пропуска или ссылок, они просто передают имя функции. Все эти методы известны как псевдо-тип callback: http://php.net/callback

Ответ 5

В PHP 5.4.4 (не тестировали более низкие или другие версии), вы можете сделать то, что вы предложили.

Возьмем это как пример:

function test ($func) {
    $func('moo');
}

function aFunctionToPass ($str) {
    echo $str;
}

test('aFunctionToPass');

script будет эхом "moo", как если бы вы сразу называли "aFunctionToPass".

Ответ 6

Вы можете сказать

$fun = 'test'; 
call($fun); 

Ответ 7

Вместо call(test); используйте call_user_func('test');.

Ответ 8

Аналогичная модель этой функции первого класса Javascript:

function add(first, second, callback){
    console.log(first+second);
    if (callback) callback();
}

function logDone(){
    console.log('done');
}

function logDoneAgain(){
    console.log('done Again');
}
add(2,3, logDone);
add(3,5, logDoneAgain);

Может быть сделано в PHP (протестировано с 5.5.9-1ubuntu на C9 IDE) следующим образом:

// first class function
$add = function($first, $second, $callback) {
  echo "\n\n". $first+$second . "\n\n";
  if ($callback) $callback();
};

function logDone(){
  echo "\n\n done \n\n";
}
call_user_func_array($add, array(2, 3, logDone));
call_user_func_array($add, array(3, 6, function(){
  echo "\n\n done executing an anonymous function!";
}));

Результат: 5 сделанных 9 выполненных анонимных функций!

Ссылка: https://github.com/zenithtekla/unitycloud/commit/873659c46c10c1fe5312f5cde55490490191e168