Какой сценарий требует использования пользователем вызова функции() в PHP
Я не понимаю функцию call_user_func () в том смысле, что я понимаю, как она работает, но я не уверен, почему она требуется или в каком контексте использовать ее в php. Насколько я понимаю, почему бы просто не вызвать функцию вместо вызова функции с функцией? Спасибо!
3 ответа:
У меня была пара ситуаций, когда это было очень необходимо. Например, когда я создавал проект, который позволял пользователю создавать части языка программирования, система обертывала определение "тега" в функцию, прежде чем запустить его по соображениям безопасности. Однако, делая это, я не могу просто вызвать эти функции, потому что я не знаю, когда мне нужно вызвать их, или даже какие имена будут. Введите call_user_func ()...
Итак, я уверен, что вы сейчас в замешательстве. Позвольте мне объяснять. Что моя система сделала, так это взяла некоторый XML и преобразовала его в PHP / HTML/JS с помощью PHP. Это позволило быстро создать ГИС (что и было целью). Возьмем, к примеру, такой XML:
<window id="login-win" title="Access Restricted" width="310" height="186" layout="accordion" layoutConfig="animate:true"> <panel id="login-panel" title="User Login"> <form id="login-form" title="Credentials"> <textbox id="login-uname" label="Username"/> <password id="login-pass" label="Password"/> <submit text="Login"/> </form> </panel> <panel id="login-register" title="Register"> Nothing, you can't register! </panel> </window>
Каждый XML-тег считывается, а затем подается в соответствующую ему функцию PHP. Эта функция определит, что делать для этого тега 1. Чтобы осуществить это, у меня были файлы, каждый из которых был назван в честь тега, который он обрабатывал. Так, например, файл тега был "submit.РНР". Содержимое этого файла будет завернуто в генерируемая функция, что-то вроде:
function tag_submit($variables, $parent, $children){ // deal with the data, then echo what is needed }
Имя этой функции будет сохранено в массиве вместе с именем тега, связанным с остальными сгенерированными функциями. Это делает его так, что функция генерируется один раз и создается только при необходимости, экономя память, так как я бы сделал вызов if(func_exists ()), чтобы определить, нужен ли он мне или нет.
Однако, поскольку все это динамично, и пользователь может захотеть добавить новый тег, например, тег , мне нужно было использовать call_user_func (), чтобы заставить вещи работать. Я не могу жестко кодировать вызов функции, если я не знаю, как это называется.
Надеюсь, что все это имело смысл. В принципе, да, это редко используемая функция, но она все еще очень и очень полезна.
Call_user_func дает PHP возможность рассматривать методы и функции как квази первоклассных граждан. В функциональных языках, таких как javascript, нет необходимости в этих специальных инструментах, поскольку функция - это объект, который может быть вызван.
PHP становится все ближе к тому, чтобы иметь такое понятие, особенно с поддержкой закрытия, которая пришла вместе с PHP5. 3. Взгляните на комментарий, который я поместил под ответом @deceze. Есть и некоторые другие инструменты (а именно переменные функции, отражение и теперьзамыкания ), которые предлагают ту же основную функциональность.
Самое примечательное в call_user_func - это то, как он позволяет обрабатывать глобальные функции, статические классы и объекты с единым интерфейсом. Это, вероятно, самое близкое, что у них есть к единому интерфейсу для вызова функций, независимо от того, как они реализованы. Внутренне основная группа разработчиков PHP работает над гомогенизацией некоторого вида что касается "вызываемого" или "вызываемого" интерфейса для языка , я уверен,что мы увидим чистое предложение в PHP5. 4 или в следующем крупном выпуске.
Именованные функции, анонимные функции, статические методы, методы экземпляра и объекты с методом "__invoke" в совокупности называются "вызываемыми". Если у меня есть вызываемый объект, его должно быть можно вызвать, поставив скобки после "() " (я предположу, что он не принимает аргументов). Это работает, когда наш вызываемый объект хранится в переменной, например:
$f(); // Call $f
Однако, что делать, если я сохраняю вызываемый объект в свойстве объекта?
$obj = new stdClass; $obj->my_func = function() {}; $obj->my_func(); // Error: stdClass does not have a "my_func" method
Проблема в том, что синтаксический анализатор PHP запутаться из-за неоднозначности кода может означать вызов вызываемого свойства или метода. PHP всегда рассматривает этот вид кода как вызов метода, поэтому мы не можем вызывать вызываемые свойства таким образом. Вот почему нам нужен 'call_user_func':
call_user_func($obj->my_func); // Calls $obj->my_func
Бывают и другие случаи, когда PHP не понимает обычного синтаксиса скобок; например, PHP в настоящее время (5.5) не знает, как вызвать возвращаемое значение другого вызываемого объекта:
get_a_callable()(); // Parse error, unexpected "(" call_user_func(get_a_callable()); // Calls the return value of get_a_callable
Это тоже не так в настоящее время возможно вызвать функцию definion напрямую, что полезно для обхода отсутствия в PHP операторов "let", например:
function($x) { echo $x . $x; }('hello'); // Parse error, unexpected "(" call_user_func(function($x) { echo $x . $x; }, 'hello'); // Calls the function
Бывают также случаи, когда полезно иметь вызовы функций / reified/ в виде функции 'call_user_func'. Например, при использовании функций более высокого порядка, таких как array_map:
$funcs = [function() { return 'hello'; }, function() { return 'world'; }]; array_map('call_user_func', $funcs); // ['hello', 'world']
Это также полезно, когда мы не знаем, сколько параметров потребуется, т. е. мы не можем заменить нашу собственную " функцию ($f, $x, $y, ...) { возвращение $Ф($Х, $У, ...); }".
Одно особенно хорошее определение-частичное приложение, которое занимает всего несколько строк благодаря call_user_func и call_user_func_array:
function partial() { $args1 = func_get_args(); // $f, $a, $b, $c, ... return function() use ($args1) { // Returns $f($a, $b, $c, ..., $d, $e, $f, ...) $args2 = func_get_args(); // $d, $e, $f, ... return call_user_func_array('call_user_func', array_merge($args1, $args2)); }; }