PHP Laravel Facade __callStatic参数列表

时间:2014-10-29 14:37:11

标签: php optimization laravel arguments

不确定如何确切地标题。在深入了解Laravel 4课程以了解外墙是如何工作的时候,我偶然发现了这个:

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。对此有合理的论据,还是只是过早优化的情况?

3 个答案:

答案 0 :(得分:4)

你是对的,在不使用call_user_func_array();声明的情况下调用switch可以完美地工作。 但是,根据这个benchmark,它看起来非常慢:

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声明的原因。

答案 1 :(得分:4)

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

我能够在call_user_func_array上的手册条目中找到这个用户提交的引用来自' noone at example dot com':

  

对于那些必须考虑性能的人:以这种方式调用函数需要的时间大约是通过直接语句的3倍,所以只要可以避免使用这种方法,这是一个明智的想法如此。

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

$ 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可以加快对静态外观方法的调用,除非静态方法的参数超过4个。

至于为什么选择4个参数的截止数,只有泰勒知道。自从Laravel 4.0 first commit以来,这种方法(大部分)都没有改变,我怀疑它有些武断。

答案 2 :(得分:3)

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

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