PHP Laravel Facade __callStatic参数列表


PHP Laravel Facade __callStatic argument list

不知道如何准确命名。在深入研究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);
    }
}

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

真正让我头疼的是开关。

为什么需要从0到4的情况,而默认情况无论如何都可以工作。

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

我怀疑这是一个微观优化。我还怀疑,大多数对facade的静态调用需要4个或更少的参数,在这种情况下,大多数静态调用不会跳到默认情况下。

我能够在call_user_func_array上的手动条目中找到这个用户提交的报价,来自"noone at example dot com":

对于那些必须考虑性能的人来说:用这种方式调用函数的时间大约是用直接语句调用函数的3倍,所以只要可行,就应该避免这种方法

做一个非常简单的基准测试似乎也证实了这一点的有效性。结果中,1直接调用实例上的方法,2在实例上调用变量方法名,3使用call_user_func_array,输出时间以秒为单位。每个方法的迭代次数为1000000。

$ 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

上面的结果表明,除非静态方法有4个以上的参数,否则避免call_user_func_array可以将对静态facade方法的调用速度至少提高2倍左右。

至于为什么选择4个参数的截止数,只有Taylor知道。自从Laravel 4.0首次提交以来,这种方法(基本上)没有改变,我怀疑它有点武断。

您是对的,在不使用switch语句的情况下调用call_user_func_array();非常有效但是,根据这个基准,它看起来非常慢:

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语句的原因。

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

考虑到这段代码可以在一个周期内被多次调用,因此尽可能优化它是有意义的。