PHP call_user_func与仅调用函数


90

我敢肯定对此有一个非常简单的解释。这有什么区别:

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');

Answers:


87

知道时始终使用实际的函数名称。

call_user_func 用于调用您事先不知道其名称的函数,但效率低得多,因为程序必须在运行时查找该函数。


谢谢你,凯。call_user_func正是我所需要的。
杰伊

44
call_user_func不一定需要。您始终可以使用变量函数来调用函数:$some_func()call_user_func_array是真正有用的那个
Ionuț G. Stan,

23
php始终需要“在运行时查找函数”
VolkerK,2009年

2
@Pacerier不正确。匿名函数仍在变量中,即$func = function(){};。call_user_func的任何可能参数都必须是可调用的,这意味着它包含足够的数据以直接访问它,无论是$func(),还是$obj->{$func}(),还是其他。
Benubird

2
“效率较低”实际上很少,尤其是自php7以来,它的调用时间约为几毫秒/百万:github.com/fab2s/call_user_func
fab2s

32

尽管您可以通过以下方式调用变量函数名称:

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);

8
我知道这已经很久了,但是在其他地方找不到文章。将call_user_func('customFunction')与$ variableFunction()并置是否更有利?有什么区别?谢谢!
David Hobs 2014年

15

call_user_func选项在那里,因此您可以执行以下操作:

$dynamicFunctionName = "barber";

call_user_func($dynamicFunctionName, 'mushroom');

其中dynamicFunctionName字符串可以更加精彩,并在运行时产生的。除非必须,否则不应该使用call_user_func,因为它比较慢。


1
在这种情况下,您似乎可以使用变量函数。
安东尼·鲁特里奇

6

我想这对于调用您不预先知道其名称的函数很有用……例如:

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

call_user_func($func, 'stuff');

5
不。我们仍然可以做$func('stuff');
ankush981

1
是的,但是使用变量的区别在于,如果使用call_user_func,则将产生PHP致命错误,而不是PHP警告。
罗伯特·布里斯塔

call_user_func()在这种情况下,这并未否定变量函数的值。
安东尼·鲁特里奇


3

调用该函数没有任何好处,因为我认为它主要用于调用“用户”函数(如插件),因为编辑核心文件不是一个好选择。这是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

0

在第一个示例中,您使用的是字符串形式的函数名。它可能来自外部,也可能是即时确定的。也就是说,您不知道在创建代码时需要运行什么功能。


-1

使用名称空间时,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。


。不真实的 $ fn ='\ Foo \ Bar \ getCurrency'; $ fn();
Jan Sverre 2014年

嗨,@ Jannis,我没有发现这是真的,也许您可​​以看到我要去哪里,我在回答中添加了更详细的示例。
ThomasRedstone 2014年

@ThomasRedstone您是否事先需要这些功能?php不会从其他文件自动加载功能。命名空间中的大小写字母也是如此。酒吧是一堂课吗?那是另一个用例。
przemo_li

@przemo_li,您好,这是一个文件(都在名称空间中),不确定名称空间名称发生了什么。为了防御,我在4年前写了答案,更新了名称空间,并添加了关于PHP 7,带有查看实际输出的链接。我仍然不知道jansverre是如何工作的,PHP 7直到2015
6
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.