【问题标题】:PHP call_user_func vs. just calling functionPHP call_user_func 与仅调用函数
【发布时间】:2009-10-20 17:46:18
【问题描述】:

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

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

【问题讨论】:

    标签: php function


    【解决方案1】:

    当你知道它时,请始终使用实际的函数名称。

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

    【讨论】:

    • call_user_func 不一定需要。您始终可以使用变量函数调用函数:$some_func()call_user_func_array 是真正有用的。
    • php 总是需要“在运行时查找函数”
    • @Pacerier 不正确。匿名函数仍在变量中,即$func = function(){};。 call_user_func 的任何可能参数都必须是可调用的,这意味着它包含足够的数据来直接访问它,无论是$func(),还是$obj->{$func}(),或者其他什么。
    • “效率较低”其实很少,尤其是从php7开始,大约是几毫秒/百万次调用:github.com/fab2s/call_user_func
    • 根据source的说法,“通过变量调用不存在的函数会导致致命错误,而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);
    

    【讨论】:

    • 我知道这已经很久了,但在其他地方找不到文章。与 $variableFunction() 相对使用 call_user_func('customFunction') 是否更有利?有什么区别?谢谢!
    【解决方案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');
    

    【讨论】:

    • 不。我们仍然可以$func('stuff');
    • 是的,但区别在于如果使用 call_user_func,使用变量将产生 PHP 致命错误与 PHP 警告。
    • 在这种情况下,这并没有否定变量函数超过call_user_func()的值。
    【解决方案5】:

    使用 PHP 7,您可以在任何地方使用更好的变量函数语法。它适用于静态/实例函数,并且可以采用一组参数。更多信息https://trowski.com/2015/06/20/php-callable-paradox

    $ret = $callable(...$params);
    

    【讨论】:

    • AFAICT,这是唯一真正回答问题的答案。
    【解决方案6】:

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

    【讨论】:

      【解决方案7】:

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

      【讨论】:

        【解决方案8】:

        当使用命名空间时,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();
        • 嗨@Jannis,我不认为这是真的,也许你可以看到我哪里出错了,我在我的答案中添加了一个更详细的例子。
        • @ThomasRedstone 您是否事先需要这些功能? php 不会从其他文件自动加载函数。还有命名空间中的小字母和大字母是什么意思。酒吧是一门课吗?那么这是另一个用例。
        • 嗨@przemo_li,这是一个单独的文件(都在命名空间内),不确定命名空间名称发生了什么,在我的辩护中,我在 4 年前写了答案,我已经更新了命名空间,并在有关 PHP 7 的注释中添加,并带有查看实际输出的链接。我仍然不知道 jansverre 是如何让它工作的,PHP 7 直到 2015 年 6 月 11 日才进入 alpha
        猜你喜欢
        • 1970-01-01
        • 2011-06-21
        • 1970-01-01
        • 1970-01-01
        • 2011-06-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多