Mot-clé `static` dans la fonction?

110

Je regardais la source de Drupal 7, et j'ai trouvé des choses que je n'avais jamais vues auparavant. J'ai fait quelques recherches initiales dans le manuel php, mais cela n'a pas expliqué ces exemples.

Que fait le mot static- clé à une variable à l'intérieur d'une fonction?

function module_load_all($bootstrap = FALSE) {
    static $has_run = FALSE
user151841
la source

Réponses:

155

Cela permet à la fonction de mémoriser la valeur de la variable donnée ( $has_rundans votre exemple) entre plusieurs appels.

Vous pouvez l'utiliser à différentes fins, par exemple:

function doStuff() {
  static $cache = null;

  if ($cache === null) {
     $cache = '%heavy database stuff or something%';
  }

  // code using $cache
}

Dans cet exemple, le ifne serait exécuté qu'une seule fois. Même si plusieurs appels doStuffse produisaient.

Yoshi
la source
4
De plus, si la fonction a été exécutée une fois, elle ne réinitialisera pas la valeur de $cacheà nulllors des appels ultérieurs, n'est-ce pas?
user151841
7
@ user151841 $cachene sera réinitialisé qu'entre les demandes. Alors oui, il ne sera pas réinitialisé sur les derniers appels dans la même requête (ou exécution du script).
Yoshi le
14
@Muhammad parce que c'est exactement ce que font les mots-clés static .
Yoshi
2
Je crois que la ifvérification de condition $cache === nullserait exécutée chaque fois que cette fonction est appelée, je ne pensais pas que le code de bloc de if $cache = '..'serait exécuté.
Aivaras
que se passe-t-il si la fonction est une méthode dans une classe, la variable statique est-elle partagée entre les instances?
santiago arizti
83

Il semble que personne ne l'a mentionné jusqu'à présent, que les variables statiques à l'intérieur de différentes instances de la même classe restent leur état. Soyez donc prudent lorsque vous écrivez du code POO.

Considère ceci:

class Foo
{
    public function call()
    {
        static $test = 0;

        $test++;
        echo $test . PHP_EOL; 
    }
}

$a = new Foo();
$a->call(); // 1
$a->call(); // 2
$a->call(); // 3


$b = new Foo();
$b->call(); // 4
$b->call(); // 5

Si vous voulez qu'une variable statique se souvienne de son état uniquement pour l'instance de classe actuelle, vous feriez mieux de vous en tenir à une propriété de classe, comme ceci:

class Bar
{
    private $test = 0;

    public function call()
    {
        $this->test++;
        echo $this->test . PHP_EOL; 
    }
}


$a = new Bar();
$a->call(); // 1
$a->call(); // 2
$a->call(); // 3


$b = new Bar();
$b->call(); // 1
$b->call(); // 2
Yang
la source
1
Aie! Cela m'a mordu plus d'une fois. Je m'attendais à ce que la statique s'applique uniquement à l'instance, fournissant une mémorisation; mais c'était une mauvaise façon de penser, car «statique» dans le contexte des classes signifie pour la classe dans son ensemble. Propriétés, méthodes et variables ET.
systemovich
14

Compte tenu de l'exemple suivant:

function a($s){
    static $v = 10;
    echo $v;
    $v = $s;
}

Premier appel de

a(20);

sortira 10, puis $vsera 20. La variable $vn'est pas récupérée après la fin de la fonction, car il s'agit d'une variable statique (non dynamique). La variable restera dans sa portée jusqu'à ce que le script se termine totalement.

Par conséquent, l'appel suivant de

a(15);

sera alors sortie 20, puis défini $vpour être 15.

Mauris
la source
9

Static fonctionne de la même manière que dans une classe. La variable est partagée entre toutes les instances d'une fonction. Dans votre exemple particulier, une fois la fonction exécutée, $ has_run prend la valeur TRUE. Toutes les futures exécutions de la fonction auront $ has_run = TRUE. Ceci est particulièrement utile dans les fonctions récursives (comme alternative au passage du nombre).

Une variable statique n'existe que dans une portée de fonction locale, mais elle ne perd pas sa valeur lorsque l'exécution du programme quitte cette portée.

Voir http://php.net/manual/en/language.variables.scope.php

tofutim
la source
3

variable statique dans une fonction signifie que peu importe le nombre de fois que vous appelez la fonction, il n'y a qu'une seule variable.

<?php

class Foo{
    protected static $test = 'Foo';
    function yourstatic(){
        static $test = 0;
        $test++;
        echo $test . "\n"; 
    }

    function bar(){
        $test = 0;
        $test++;
        echo $test . "\n";
    }
}

$f = new Foo();
$f->yourstatic(); // 1
$f->yourstatic(); // 2
$f->yourstatic(); // 3
$f->bar(); // 1
$f->bar(); // 1
$f->bar(); // 1

?>
Pwnna
la source
3

Pour développer la réponse de Yang

Si vous étendez une classe avec des variables statiques, les classes étendues individuelles contiendront leur «propre» statique référencée qui est partagée entre les instances.

<?php
class base {
     function calc() {
        static $foo = 0;
        $foo++;
        return $foo;
     }
}

class one extends base {
    function e() {
        echo "one:".$this->calc().PHP_EOL;
    }
}
class two extends base {
    function p() {
        echo "two:".$this->calc().PHP_EOL;
    }
}
$x = new one();
$y = new two();
$x_repeat = new one();

$x->e();
$y->p();
$x->e();
$x_repeat->e();
$x->e();
$x_repeat->e();
$y->p();

les sorties:

un: 1
deux : 1
un: 2
un : 3 <- x_repeat
un: 4
un : 5 <- x_repeat
deux : 2

http://ideone.com/W4W5Qv

Tschallacka
la source
1

À l'intérieur d'une fonction, cela staticsignifie que la variable conservera sa valeur chaque fois que la fonction est appelée pendant la durée de vie du chargement de la page.

Par conséquent, dans l'exemple que vous avez donné, si vous appelez une fonction deux fois, si elle est définie $has_runsur true, alors la fonction pourra savoir qu'elle a été précédemment appelée car elle $has_runserait toujours égale au truemoment où la fonction démarre la deuxième fois.

L'utilisation du staticmot - clé dans ce contexte est expliquée dans le manuel PHP ici: http://php.net/manual/en/language.variables.scope.php

Spudley
la source