PHP call_user_func против просто вызывающей функции

Я уверен, что для этого очень простое объяснение. В чем разница между ними:

function barber($type){
    echo "You wanted a $type haircut, no problem\n";
}
call_user_func('barber', "mushroom");
call_user_func('barber', "shave");

... и это (и каковы преимущества?):

function barber($type){
    echo "You wanted a $type haircut, no problem\n";
}
barber('mushroom');
barber('shave');

Ответ 1

Всегда используйте имя фактической функции, когда вы ее знаете.

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

Ответ 2

Хотя вы можете вызвать имена переменных функций следующим образом:

function printIt($str) { print($str); }

$funcname = 'printIt';
$funcname('Hello world!');

Есть случаи, когда вы не знаете, сколько аргументов вы передаете. Рассмотрим следующее:

function someFunc() {
  $args = func_get_args();
  // do something
}

call_user_func_array('someFunc',array('one','two','three'));

Это также удобно для вызова статических и объектных методов, соответственно:

call_user_func(array('someClass','someFunc'),$arg);
call_user_func(array($myObj,'someFunc'),$arg);

Ответ 3

существует опция call_user_func, поэтому вы можете делать такие вещи, как:

$dynamicFunctionName = "barber";

call_user_func($dynamicFunctionName, 'mushroom');

где строка dynamicFunctionName может быть более захватывающей и сгенерирована во время выполнения. Вы не должны использовать call_user_func, если это необходимо, потому что оно медленнее.

Ответ 4

Я предполагаю, что это полезно для вызова функции, которой вы не знаете имя заранее... Что-то вроде:

switch($value):
{
  case 7:
  $func = 'run';
  break;
  default:
  $func = 'stop';
  break;
}

call_user_func($func, 'stuff');

Ответ 5

Нет никаких преимуществ, вызывающих такую ​​функцию, потому что я думаю, что в основном она используется для вызова функции "пользователь" (например, плагина), потому что редактирование файла ядра не является хорошим вариантом. вот грязный пример, используемый Wordpress

<?php
/* 
* my_plugin.php
*/

function myLocation($content){
  return str_replace('@', 'world', $content);
}

function myName($content){
  return $content."Tasikmalaya";
}

add_filter('the_content', 'myLocation');
add_filter('the_content', 'myName');

?>

...

<?php
/*
* core.php
* read only
*/

$content = "hello @ my name is ";
$listFunc = array();

// store user function to array (in my_plugin.php)
function add_filter($fName, $funct)
{
  $listFunc[$fName]= $funct;
}

// execute list user defined function
function apply_filter($funct, $content)
{
  global $listFunc;

  if(isset($listFunc))
  {
    foreach($listFunc as $key => $value)
    {
      if($key == $funct)
      {
        $content = call_user_func($listFunc[$key], $content);
      }
    }
  }
  return $content;
}

function the_content()
{
  $content = apply_filter('the_content', $content);
  echo $content;
}

?>

....

<?php
require_once("core.php");
require_once("my_plugin.php");

the_content(); // hello world my name is Tasikmalaya
?>

Выход

hello world my name is Tasikmalaya

Ответ 6

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

Ответ 7

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

$function = '\Utilities\SearchTools::getCurrency';
call_user_func($function,'USA');

Если все ваши функции находились в одном и том же пространстве имен, это не было бы такой проблемой, поскольку вы могли бы использовать что-то вроде этого:

$function = 'getCurrency';
$function('USA');

Изменить: Следуя @Jannis, заявив, что я ошибаюсь, я сделал немного больше тестов и не имел большой удачи:

<?php
namespace Foo {

    class Bar {
        public static function getBar() {
            return 'Bar';
        }
    }
    echo "<h1>Bar: ".\Foo\Bar::getBar()."</h1>";
    // outputs 'Bar: Bar'
    $function = '\Foo\Bar::getBar';
    echo "<h1>Bar: ".$function()."</h1>";
    // outputs 'Fatal error: Call to undefined function \Foo\Bar::getBar()'
    $function = '\Foo\Bar\getBar';
    echo "<h1>Bar: ".$function()."</h1>";
    // outputs 'Fatal error: Call to undefined function \foo\Bar\getBar()'
}

Вы можете увидеть результаты вывода здесь: https://3v4l.org/iBERh кажется, что второй метод работает для PHP 7, но не PHP 5.6.