Ce sont des variables statiques étranges en PHP

Avertissement: cet article ne vous révélera aucune révélation et n'ouvrira pas le troisième œil, mais vous permettra de comprendre plus en détail la question pas si évidente. Au moins quand je l'ai écrit, elle m'a aidé dans ce domaine. Si vous êtes un loup chevronné en php, vous ne pouvez pas le lire, je pense que cela ne fera pas de mal aux personnes expérimentées de courir dans leurs yeux, de les rafraîchir en mémoire, pour ainsi dire, le reste sera normal.


Alors ...


Les variables statiques en php sont un type spécial de variable qui est déclaré à l'aide du mot-clé statique .


static $foo = 3; 

Ils diffèrent des variables ordinaires en ce sens (plus loin dans l'article, ces points seront examinés plus en détail):


  1. seules les constantes et expressions constantes peuvent être affectées
  2. la durée de vie d'une variable statique n'est pas limitée à la durée de vie de l'étendue dans laquelle elle a été déclarée
  3. ne peut être défini dans le script qu'une seule fois
  4. pas détruit jusqu'à la fin du script

Maintenant en ordre.


1. Seules les constantes et les expressions constantes peuvent être affectées


Cela signifie que le résultat du fonctionnement d'une fonction ou d'une méthode ne peut pas être affecté à une variable statique, ou en général à tout ce qui n'est pas encore connu au stade de la compilation. Autrement dit, une telle annonce ne fonctionnera pas


 static $var = foo(); 

mais c'est tout à fait possible


 static $var = 'some str'; static $varInt = 3 + 5; 

2. La durée de vie d'une variable statique n'est pas limitée à la durée de vie de l'étendue dans laquelle elle est déclarée


Je vais essayer d'expliquer ce que je voulais dire ici. Je vais peut-être faire quelques inexactitudes dans la terminologie, mais je vais essayer de transmettre l'essence aussi précisément que possible. Comparez avec une variable régulière. Si une variable est déclarée à l'intérieur d'une fonction, alors par défaut c'est une variable locale, c'est-à-dire qu'elle est déclarée dans la portée locale (portée de cette fonction). Dans ce cas, le contexte de cette fonction sera la portée locale. Une fois que la fonction a fonctionné et renvoyé le résultat, sa portée ou son contexte, avec toutes les variables à l'intérieur, sera détruit.


Si nous déclarons une variable statique à l'intérieur de la fonction, alors elle est également déclarée dans la portée locale, mais son contexte ne sera pas la portée locale, mais la fonction elle-même.


(De plus, le moment le plus difficile à expliquer, je ne passe que l'essentiel, sans détails, comment les fonctions sont déclarées en php combien de mémoire leur est allouée et ce qui se trouve dans cette mémoire). Il s'avère que, lorsqu'une fonction est appelée, l'interpréteur lui crée une portée locale, c'est en elle que toutes les variables et fonctions locales sont déclarées, et y sont attachées comme à leur contexte. En déclarant une variable dans la portée locale à l'aide de statique, la fonction elle-même est affectée à cette variable en tant que contexte, et cette variable existera tant que la fonction elle-même existera. C'est quelque chose comme js lorsqu'une fonction est un objet dans lequel vous pouvez affecter des propriétés et des méthodes arbitraires. Ici aussi, seule une fonction en php est un objet non pas pour php, mais pour un langage inférieur.


 function echoStaticVar() { static $var = 0; $var++; var_dump($var); }; echoStaticVar(); //1 echoStaticVar(); //2 echoStaticVar(); //3 

On voit qu'après la fin de la fonction, le collecteur ne détruit pas la variable $ var comme il le ferait avec une variable régulière.


Et voici un exemple qui montrera clairement qu'une variable statique appartient à une fonction (soit elle est stockée dans une fonction, soit son contexte est une fonction, donc je suis désolé de ne pas savoir comment la nommer correctement).


 $one = function ($i) { static $var = 0; $var += $i; var_dump($var); }; $two = $one; $one(1); //1 $one(5); //6 $one(5); //11 $two(5); //16 $two(5); //21 

Tout fonctionne comme prévu, car lors de l'attribution de $ two = $ one; la fonction elle-même n'est pas copiée, mais simplement ces deux variables feront référence à la même zone mémoire. Par conséquent, la variable statique $ var sera une pour $ un et $ deux


On change un peu l'exemple, à savoir, on n'attribue pas, mais on clone


 // $two = $one; // $two = clone($one); 

 $one = function ($i) { static $var = 0; $var += $i; var_dump($var); }; $two = clone($one); $one(1); //1 $one(5); //6 $one(5); //11 $two(5); //5 $two(5); //10 

Maintenant, il s'est avéré que $ one et $ two ne se réfèrent pas à la même fonction avec une variable statique $ var, mais à deux fonctions différentes qui se trouvent dans des zones de mémoire différentes et chacune ont sa propre variable statique $ var. Ce n'est pas un point particulièrement évident, vous pouvez donc y tomber, si bien sûr vous écrivez généralement du code dans un style procédural, ce qui est probablement déjà considéré comme une mauvaise forme, mais ce n'est pas exact).


Ce que vous pouvez faire avec ceci est un exemple classique d'un compteur d'appels de fonction.
Mais en ce qui concerne la propagation de la POO sous cette forme, les variables statiques sont rares, car fondamentalement, vous devez fonctionner avec des classes et des méthodes (j'écrirai un article séparé sur l'implémentation de la statique en elles)


3. ne peut être défini dans le script qu'une seule fois


Cela signifie que si une variable statique est déjà déclarée et qu'une valeur lui est affectée, les affectations suivantes ne remplaceront pas la valeur déjà affectée, mais renverront celle existante.


 function staticVar($i) { static $var = 0; $var += $i; var_dump($var); }; staticVar(1); //1 staticVar(5); //6 staticVar(5); //11 

On peut voir que si la variable statique $ var avait à chaque fois une valeur réaffectée, alors nous obtiendrions toujours le résultat 1. Mais comme elle n'est pas réécrite lors de la réaffectation, nous obtenons ce que nous obtenons.
Certes, il y a une chose qui peut tout gâcher. Dans le cadre d'une fonction (plus précisément, la première fois que la fonction est appelée), une telle variable peut être réécrite autant de fois que vous le souhaitez (dans la suite, tout fonctionnera comme indiqué). Ce comportement m'a semblé étrange et drôle, surtout si vous jouez avec des exemples.


 function staticVar($i) { static $var = 0; static $var = 5; $var += $i; var_dump($var); }; staticVar(1); //6 staticVar(5); //11 staticVar(5); //16 

Ici, la variable $ var dans le premier appel à la fonction staticVar dans sa première ligne a été affectée, puis remplacée dans la deuxième ligne. Mais déjà dans d'autres appels, ni dans la première ni dans la deuxième ligne, elle a été réaffectée, mais a renvoyé ce qui était déjà dans l'appel précédent


 function staticVar($i) { static $var = 0; // static $var = 5; //    $var += $i; static $var = 0; //    var_dump($var); }; staticVar(1); //1 staticVar(5); //6 staticVar(5); //11 

Encore plus étrange au premier appel de staticVar dans la première ligne, il a été attribué, puis dans la deuxième ligne, il a été réaffecté (mais sans succès), puis une action d'addition a été effectuée avec lui, et après cela, lorsque vous essayez de le réaffecter même dans le premier appel de fonction, il a renvoyé celui déjà en son sens.


 function staticVarWrong($i) { static $var = 0; static $var = 5; $var += $i; var_dump($var); }; //  staticVarWrong(1); //6 staticVarWrong(5); //11 staticVarWrong(5); //16 function staticVarRight($i) { static $var = 0; static $var = 5; $var += $i; static $var = 0; //    var_dump($var); }; //  staticVarRight(1); //1 staticVarRight(5); //6 staticVarRight(5); //11 

Autrement dit, il se révèle dans presque les mêmes méthodes, un comportement différent. De plus, sur la base de la description du comportement des variables statiques, le résultat correct est obtenu dans staticVarRight . Dans staticVarWrong, il s'avère (basé sur le comportement de la fonction) que dans la deuxième ligne de la fonction la variable a été redéfinie.
Cela m'a beaucoup amusé.


4. ne sont pas détruits avant la fin du script


Je ne vois pas grand intérêt à expliquer ce point, d'autant plus que tout est clair à partir des exemples. Pendant que le script est en cours d'exécution et qu'il existe une fonction pour laquelle une variable statique est déclarée, cette variable existe.


Comme prévu, il s'agit du premier article sur statique , devant la POO, les champs statiques, les méthodes.
Eh bien, bien sûr, si c'est au moins quelqu'un sera intéressé et pas difficile à blâmer.

Source: https://habr.com/ru/post/fr467489/


All Articles