PHP Laravel门面__callStatic参数列表

6

不确定如何准确地命名这个标题。在研究 Laravel 4 类以了解 Facades 工作原理时,我偶然发现了以下内容:

Illuminate\Support\Facades\Facades.php@__callStatic

public static function __callStatic($method, $args)
{
    $instance = static::getFacadeRoot();

    switch (count($args))
    {
        case 0:
            return $instance->$method();

        case 1:
            return $instance->$method($args[0]);

        case 2:
            return $instance->$method($args[0], $args[1]);

        case 3:
            return $instance->$method($args[0], $args[1], $args[2]);

        case 4:
            return $instance->$method($args[0], $args[1], $args[2], $args[3]);

        default:
            return call_user_func_array(array($instance, $method), $args);
    }
}

据我所知,这种方法调用外观引用的类的任何给定方法并传递参数。我可能错了,但这是我目前的理解。

真正困扰我的部分是switch语句。

为什么需要0到4个case,当默认情况下default case可以工作呢。

即使case 0在没有参数的情况下有点意义,为什么要有case 1-4而不是继续到case 10之类的情况。这是否有合理的论据,还是只是过早优化的情况?

3个回答

6
我怀疑这是一种微观优化。我还怀疑大多数对门面的静态调用需要4个或更少的参数,这种情况下大多数静态调用不会跳转到默认情况。
我在call_user_func_array的手册条目中找到了这个用户提交的引用,来自“noone at example dot com”:
“对于那些必须考虑性能的人:用这种方式调用函数大约需要3倍的时间,比直接使用语句调用函数要慢得多,因此只要有可能避免使用这种方法,就明智地这样做。”
非常简单的基准测试也似乎证实了其有效性。结果中,1直接在实例上调用方法,2在实例上调用变量方法名称,3使用call_user_func_array,输出时间以秒为单位。每种方法的迭代次数为100万。
$ php test.php  
(1) total: 0.51281404495239 
(2) total: 0.51285219192505 
(3) total: 1.1298811435699 
$ php test.php  
(1) total: 0.49811697006226 
(2) total: 0.5209321975708 
(3) total: 1.1204349994659 
$ php test.php  
(1) total: 0.48825788497925 
(2) total: 0.51465392112732 
(3) total: 1.156769990921

上述结果表明,避免使用call_user_func_array可以将对静态门面方法的调用速度至少提高约2倍,除非静态方法具有超过4个参数。
至于为什么选择了4个参数作为截止数字,只有Taylor知道。该方法自Laravel 4.0的第一次提交以来(大多数情况下)未发生变化,我认为这是相当任意的。

4

您说得没错,使用call_user_func_array();可以完美地运行而不使用switch语句。但是,根据这个基准测试结果,它似乎非常慢:

function html($value)
{
    return htmlentities($value);
}

name            : diff     : total    : description
native          : 0.614219 : 0.613295 : htmlentities($value)
literal_func    : 0.745537 : 1.346594 : html($value)
variable_func   : 0.826048 : 2.162376 : $func($value)
literal_method  : 0.957708 : 3.127519 : $object->html($value)
variable_method : 0.840837 : 3.970290 : $object->$func($value)
call_func       : 1.006599 : 4.993930 : call_user_func($func, $value)
call_object     : 1.193323 : 6.215677 : call_user_func((array($object, $func), $value)
cufa_func       : 1.232891 : 7.320287 : call_user_func_array($func, array($value))
cufa_object     : 1.309725 : 8.769755 : call_user_func_array((array($object, $func), array($value)

实际上,只有在多次使用call_user_func_array()时(这在Laravel中是常见的情况)才会出现这个问题。这就是为什么他们使用switch语句。


3

因为$instance->$method()call_user_func_array要快得多。

考虑到在一个循环中可能会多次调用这段代码,因此尽可能地优化它是有意义的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接