Tout sur le mot clé statique

Aujourd'hui, nous allons apprendre à utiliser le mot clé 'static' en PHP. Nous allons passer en revue les bases et construire quelques exemples. Il est temps d'ajouter cette fonctionnalité linguistique intéressante à votre truc de développement Web..


1 Un exemple rapide

Restons d'abord avec un exemple rapide, pour voir l'effet de l'utilisation du mot clé static.

Imaginez écrire une fonction qui rappelle le nombre total de fois où elle a été appelée. Si vous ne connaissez pas le mot clé 'static', vous pouvez recourir à une variable globale:

 $ call_me_count = 0; function call_me () global $ call_me_count; $ call_me_count ++; echo "Tu m'as appelé $ call_me_count fois 
\ n "; // output => Tu m'as appelé 1 fois call_me (); // output => Tu m'as appelé 2 fois call_me (); // output => Tu m'as appelé 3 fois call_me (); // output => Vous m'avez appelé 4 fois call_me ();

Ce n'est pas parce que cela fonctionne que vous devriez écrire du code de cette façon. De manière générale, les variables globales sont mal vues. Ce n'est pas une bonne idée d'avoir des variables globales flottantes, que certaines fonctions utilisent uniquement en privé.

Maintenant, entrez le mot clé 'statique'. Le même code peut être réécrit comme ceci:

 function call_me () // une variable statique static $ call_me_count = 0; $ call_me_count ++; echo "Tu m'as appelé $ call_me_count fois 
\ n "; // output => Tu m'as appelé 1 fois call_me (); // output => Tu m'as appelé 2 fois call_me (); // output => Tu m'as appelé 3 fois call_me (); // output => Vous m'avez appelé 4 fois call_me ();

Même résultat, plus de variables globales. Mais comment ça marche exactement?

Normalement, toutes les variables locales d'une fonction sont détruites au retour de la fonction. Les mots-clés 'static' permettent à PHP de garder la variable active. Donc, la prochaine fois que la fonction est appelée, la valeur à l'intérieur de la variable est conservée.


2 valeurs initiales valides

Comme dans l'exemple précédent, lorsque nous avons affecté la valeur 0 à la variable, celle-ci n'a pas exécuté une instruction d'affectation. Il ne définit que la valeur initiale de la variable. Cela peut sembler la même chose, mais il y a une légère différence. La variable ne peut être initialisée qu'à une valeur fixe et non à une expression.

Voyons quelques exemples de valeurs initiales valides et invalides. Tout d'abord, regardons les chiffres:

 function foo () // valide statique $ a = 9; // provoque une erreur d'analyse static $ a = sqrt (81); // valide static $ a = 3.14; // provoque une erreur d'analyse static $ a = pi (); // provoque une erreur d'analyse static $ a = 1 + 3; 

Comme vous pouvez le constater, même les opérations mathématiques de base ne sont pas autorisées. Tout ce que vous pouvez attribuer est un nombre fixe.

Nous pouvons aussi assigner des chaînes:

 function foo () // static $ a = "; // static $ a = 'bonjour'; // provoque une erreur d'analyse static $ a = strtoupper ('hello'); // provoque une erreur d'analyse static $ a = 'Bonjour le monde'; 

Encore une fois, il faut que ce soit des chaînes fixes, et même la concaténation de base n'est pas autorisée.

Les booléens, les tableaux et les constantes fonctionneront aussi:

 define ("SOME_CONSTANT", 789); function foo () // statique valide $ a = array (1,2,3); // valide static $ a = SOME_CONSTANT; // valide $ $ = = array (1,2, 'trois', array ('foo' => 'bar')); // valide static $ a = true; 

3 Construire une fonction Alternate ()

Maintenant que nous savons comment fonctionnent les variables statiques dans les fonctions, construisons quelque chose d'utile avec.

Voici une simple page HTML contenant un simple tableau:

    Ma table    
ID prénom Catégorie
1 Pomme Fruit
2 Carotte Légume
3 Chien Animal
4 Four Appareil

Le résultat est:


Ajoutons maintenant quelques css et faisons en sorte que les lignes changent de couleur:

    Ma table     
ID prénom Catégorie
1 Pomme Fruit
2 Carotte Légume
3 Chien Animal
4 Four Appareil

Maintenant ça ressemble à ça:


Si les données provenaient d'une base de données et que les lignes de la table étaient sorties dans une boucle, vous devrez ajouter du code pour pouvoir définir ces classes CSS alternées sur chaque ligne. La plupart des gens se contentent de créer une variable dans cette boucle, d'ajouter une instruction conditionnelle ou ternaire pour conserver sa valeur en alternance..

Cependant, nous allons construire une solution plus élégante et réutilisable. Nous allons créer une fonction nommée alternate () qui utilise le concept de variables statiques.

 fonction alternative ($ a, $ b) statique $ alt = false; // inverse la valeur de alt (true <=> false) $ alt =! $ alt; if ($ alt) return $ a; // retourne la première valeur else return $ b; // retourne la deuxième valeur // Exemple d'utilisation: // output: odd echo altern ('impair', 'pair'); // output: even echo altern ('impair', 'pair'); // sortie: impair écho alterné ('impair', 'pair');

Nous appelons la fonction avec deux arguments. Chaque fois qu'il est appelé, il retourne l'un des arguments en alternance. Pour ce faire, il conserve une valeur booléenne dans une variable statique appelée $ alt. Chaque fois qu'il retourne cette valeur de variable, déterminer lequel des deux arguments à renvoyer.

Alors, utilisons cela dans notre page, en regroupant tout cela:

  false) $ alt =! $ alt; if ($ alt) return $ a; // retourne la première valeur else return $ b; // retourne la deuxième valeur $ rows = array (tableau (1, 'Pomme', 'Fruit'), tableau (2, 'Carotte', 'Légume'), tableau (3, 'Chien', 'Animal') , tableau (4, 'Four', 'Appareil')); ?>    Ma table     
ID prénom Catégorie
', $ row); ?>

Et le résultat final est le même:



4 Améliorer notre fonction Alternate ()

La fonction que nous avons créée fonctionne bien si nous l’utilisons uniquement à un endroit de nos scripts. Cependant, il y a un petit problème. Si nous l'utilisons à plusieurs endroits ou dans des boucles imbriquées, il se peut que les valeurs ne soient pas renvoyées dans l'ordre prévu. Regardons ce code pour illustrer ce problème:

 // un écho alterné ('a', 'b'). "
\ n "; // b echo alter ('a', 'b')."
\ n "; // un écho alternatif ('a', 'b')."
\ n "; // pair // (la deuxième valeur est renvoyée en premier!) echo alter ('impair', 'pair')."
\ n "; // étrange écho alterné ('impair', 'pair')."
\ n "; // bar // (même problème) echo alter ('foo', 'bar')."
\ n "; // a // (la dernière fois, c’était aussi 'a) echo alter (' a ',' b ')."
\ n ";

Notre fonction doit savoir qu’elle est appelée de différents endroits et s’assurer de renvoyer les valeurs en conséquence. Nous pouvons accomplir cela en ajoutant un dernier paramètre facultatif, pour attribuer un numéro d'identification. Et nous transmettons un ID unique provenant de chaque endroit différent d'où nous l'appelons, afin d'éviter ces conflits:

 fonction alternative ($ a, $ b, $ id = 0) statique $ alt = array (); if (! isset ($ alt [$ id])) alt alt [$ id] = false;  $ alt [$ id] =! $ alt [$ id]; if ($ alt [$ id]) return $ a;  else return $ b;  // un écho alternatif ('a', 'b', 1). "
\ n "; // b écho alterné ('a', 'b', 1)."
\ n "; // un écho alternatif ('a', 'b', 1)."
\ n "; // étrange écho alterné ('impair', 'pair', 2)."
\ n "; // même echo alternes ('impair', 'pair', 2)."
\ n "; // foo echo alter ('foo', 'bar', 3)."
\ n "; // b écho alterné ('a', 'b', 1)."
\ n ";

Cette fois, nous utilisons un tableau comme variable statique. Il portera une valeur booléenne unique pour chaque numéro d'identification transmis. Cela lui permet de renvoyer les valeurs dans le bon ordre.


5 membres de classe statiques

Le mot clé 'statique' n'est pas seulement utilisé dans les fonctions. C'est en fait assez courant en programmation orientée objet. Il peut y avoir des membres statiques et des méthodes. Nous allons d’abord examiner le fonctionnement des membres statiques.

Voici la syntaxe:

 class Foo // un membre statique public static $ a = 0; // un membre normal public $ b = 0; fonction publique bar () // accédant au membre statique self :: $ a; self :: $ a ++; soi :: $ a = 3; // membre normal: $ this-> b; $ this-> b ++; $ this-> b = 3;  // accédant au membre statique // de l'extérieur de Foo :: $ a; Foo :: $ a ++; Foo :: $ a = 3; $ obj = new Foo (); // accédant au membre normal $ obj-> b; $ obj-> b ++; $ obj-> b = 3;

Notez comment nous avons utilisé le mot clé 'self ::' devant la variable statique pour y accéder au sein de la classe, plutôt que '$ this'. De plus, lorsqu'il est utilisé dans l'étendue externe, il n'est pas nécessaire de créer une instance de l'objet avant de pouvoir accéder aux variables statiques. Cependant, les membres de classe normaux ne sont accessibles que lorsque nous en avons créé une instance..


6 Une classe qui compte

Rappelez-vous notre premier exemple où nous avions une fonction qui comptait combien de fois elle était appelée. Appliquons maintenant le même principe à la programmation orientée objet.

Cette classe pourra compter combien de fois elle a été créée:

 class Foo // notre compteur d'instances public static $ counter = 0; // pour travailler en tant qu'ID d'auto-incrémentation public $ id = 0; // la fonction constructeur public function __construct () // increment counter self :: $ counter ++; // enregistre le même numéro // que l'identifiant de cet objet $ this-> id = self :: $ counter;  // résultat: 0 echo Foo :: $ counter. "\ n
"; $ a = new Foo (); // sortie: 1 echo Foo :: $ counter." \ n
"; $ b = new Foo (); // sortie: 2 echo Foo :: $ counter." \ n
"; $ c = new Foo (); // sortie: 3 echo Foo :: $ counter." \ n
"; // résultat: 2 echo $ b-> id;

Chaque fois qu'un nouvel objet est créé, la fonction constructeur est appelée par défaut. Cette fonction contient un code permettant de définir le compteur et le numéro d’identification de cette instance de l’objet. Ainsi, si un objet a été créé pour la troisième fois, cet objet aura un identifiant de 3, qui est spécifique à cet objet uniquement. Le compteur continuera à monter au fur et à mesure que de nouveaux objets seront créés.

Notez que les membres de classe normaux existent séparément sur chaque objet. Cependant, les membres statiques n'existent qu'une fois globalement.


7 méthodes de classe statique

Non seulement les membres, mais aussi les méthodes d'une classe peuvent être rendues «statiques».

 class Foo // remarque le mot-clé static public static function hello () echo "Hello World"; 

Et voici comment vous pouvez les appeler:

 Foo :: bonjour (); // imprime Hello World

Notez que la syntaxe est similaire à celle utilisée pour accéder aux membres statiques, en utilisant deux points-virgules (: :).

À l'intérieur d'une méthode statique, une classe peut se référer à elle-même à l'aide du mot clé 'self' et accéder aux membres statiques de cette façon

 classe Foo public static $ call_me_count = 0; fonction statique publique call_me () self :: $ call_me_count ++; echo "Vous m'avez appelé" .self :: $ call_me_count. "times 
\ n "; // output => Tu m'as appelé 1 fois Foo :: call_me (); // output => Tu m'as appelé 2 fois Foo :: call_me (); // output => Tu m'as appelé 3 fois Foo :: call_me (); // output => Vous m'avez appelé 4 fois Foo :: call_me ();

8 Le modèle Singleton

Un 'Singleton' est une classe qui ne peut exister qu'en tant qu'instance d'objet unique. Il contient également une référence statique à cette instance..

Cela pourrait devenir plus clair en regardant le code:

 class Foo // doit contenir une instance de Foo private static $ instance; // rendant le constructeur privé, afin qu'il ne puisse pas être appelé de l'extérieur de la fonction privée __construct ()  // la méthode singleton fonction statique publique getInstance () // si l'instance n'existe pas encore, créez-la si (! isset (self :: $ instance)) $ c = __CLASS__; self :: $ instance = new $ c;  // retourne la seule instance return self :: $ instance;  // le clonage n'est pas autorisé public function __clone () trigger_error ('Le clonage n'est pas autorisé.', E_USER_ERROR); 

C'est la structure du squelette. Vous pouvez bien sûr ajouter plus de méthodes et de membres, ou simplement étendre la classe.

Lorsque nous appelons la méthode getInstance (), deux événements se produisent.

 $ var = Foo :: getInstance ();

Tout d'abord, s'il n'y a pas d'objet Foo, il est créé et affecté à Foo :: $ instance. Ensuite, une fois qu'il y a cet objet, il est retourné, donc $ var devient cet objet. Si vous l'appelez plusieurs fois, vous obtiendrez à chaque fois le même objet. une nouvelle instance ne sera pas créée.

 $ var = Foo :: getInstance (); $ var2 = Foo :: getInstance (); // $ var et $ var2 font référence au même objet

Depuis que nous avons rendu la méthode __construct () privée, nous ne pouvons pas créer de nouvelles instances de cet objet..

 // cela provoquera une erreur $ var = new Foo ();

9 Une classe Singleton CurrentUser

Il est maintenant temps de construire un exemple plus concret avec le motif Singleton.

Imaginez que vous ayez une classe d’utilisateur avec différentes méthodes:

 utilisateur de classe public $ id; nom public $; public $ email; fonction publique load_user ($ id) // extraction de la base de données //… fonction publique update_user ($ info) // mettre à jour la base de données avec le tableau $ info donné //… fonction publique comment_count () // calculer le nombre de commentaires //…  

Nous avons une méthode pour récupérer un utilisateur par identifiant de la base de données. Donc, il pourrait être utilisé comme ceci:

 $ utilisateur = nouvel utilisateur (); $ user-> load_user ($ user_id); // maintenant je peux voir le nom et d'autres choses echo $ user-> name; echo $ user-> comment_count ();

Maintenant, imaginez qu’une fois l’utilisateur connecté, vous stockiez son identifiant dans la session. Et lors du prochain chargement d'une page, vous devez rechercher cet identifiant et créer à nouveau l'objet $ user associé pour cet utilisateur, si vous souhaitez accéder aux membres et aux méthodes de cet objet..

Mais en raison de problèmes de portée variable, vous devrez soit rendre l’objet $ utilisateur global, soit continuer à l’initialiser à partir de différentes fonctions / méthodes de votre script. Voici où une classe singleton peut être utile:

 La classe CurrentUser étend User private static $ instance; fonction privée __construct () // assurez-vous d'appeler le constructeur parent parent :: __ construct ();  fonction statique publique getInstance () // initialise if (! isset (self :: $ instance)) // la session existe-t-elle? if (! $ _ SESSION ['user_id']) return false;  $ c = __CLASS__; self :: $ instance = new $ c; self :: $ instance-> load_user ($ _SESSION ['user_id']);  return self :: $ instance;  public function __clone () trigger_error ('Le clonage n'est pas autorisé.', E_USER_ERROR); 

Nous pouvons maintenant accéder à la classe CurrentUser de partout dans notre application:

 $ user = CurrentUser :: getInstance (); if (! $ user) echo "Vous n'êtes pas connecté!";  else echo Bienvenue back $ user-> name ";

Donc, dans notre code, nous n’avions pas à nous soucier de traiter avec session. Nous pouvons simplement essayer d’obtenir l’instance de l’objet CurrentUser et de l’utiliser comme tout objet User, car il étend ses fonctionnalités..


Conclusion

J'espère que vous avez apprécié ce tutoriel et en avez tiré des leçons. À la prochaine!