2014-10-29 14 views
6

Non so come intitolare esattamente questo. Mentre scavando nelle classi laravel 4 per vedere come Facciate lavoro, mi sono imbattuto in questo:PHP Laravel Facade __callStatic lista di argomenti

Illuminate\Support\Facades\[email protected]__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); 
    } 
} 

Ora da quello che posso dire Questo metodo chiama qualsiasi metodo della classe dei riferimenti per facciate e passa gli argomenti insieme. Potrei sbagliarmi ma questa è la mia comprensione finora.

La parte che mi infastidisce è l'interruttore.

Perché i casi da 0 a 4 sono necessari quando il caso predefinito funziona indipendentemente.

Anche se il caso 0 ha senso se non ci sono argomenti, perché avere il caso 1-4 e non solo continuare per il caso 10 per esempio. C'è un argomento ragionevole per questo o è solo un caso di ottimizzazione prematura?

risposta

4

Ho il sospetto che si tratti di una micro-ottimizzazione. Sospetto anche che la maggior parte di queste chiamate statiche alle facciate richiederebbe 4 o meno argomenti, nel qual caso la maggior parte delle chiamate statiche non passerebbe al caso predefinito.

sono stato in grado di trovare questa citazione inviati dall'utente nella voce manuale sul call_user_func_array da 'nessuno a esempio dot com':

Per quelli di voi che hanno a prendere in considerazione le prestazioni: ci vogliono circa 3 volte il tempo di chiamare la funzione in questo modo piuttosto che attraverso un'istruzione diretta, quindi ogni volta che è possibile evitare questo metodo è una saggia idea farlo.

Facendo un semplice punto di riferimento molto sembra anche confermare la validità di questo. Nei risultati, 1 sta chiamando direttamente un metodo su un'istanza, 2 sta chiamando un nome di metodo variabile su un'istanza e 3 sta utilizzando call_user_func_array e il tempo di uscita è espresso in secondi. Il numero di iterazioni per ciascun approccio è 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 

I risultati precedenti indicano che evitando call_user_func_array potrebbe accelerare chiamate ai metodi facciata statici almeno di un fattore di 2, a meno che il metodo statico ha più di 4 argomenti.

Per quanto riguarda il motivo per cui è stato scelto il numero limite di 4 parametri, solo Taylor lo sa. Quel metodo è stato (per lo più) immutato da Laravel 4.0 first commit, e sospetto che sia alquanto arbitrario.

3

Perché $instance->$method() è modo più veloce di call_user_func_array.

Dato che questo pezzo di codice può essere chiamato molte volte in un singolo ciclo, ha senso ottimizzarlo il più possibile.

4

Avete ragione, chiamando call_user_func_array(); funziona perfettamente senza utilizzare la dichiarazione switch. Ma, secondo questa benchmark, sembra terribilmente lento:

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) 

Quindi, in pratica questo diventa un problema solo quando si utilizza call_user_func_array() un sacco di volte (questo è il caso in laravel). Ecco perché usano la dichiarazione switch.

Problemi correlati