438 Chapitre 11. Récapitulatif PHP n’est donc pas sauvegardée entre deux appels. Les variables statiques, elles, sont persistantes entre deux appels. Variables globales. En principe, le corps d’une fonction est une partie de code com- plètement isolée. En particulier, les variables définies à l’extérieur de la fonction ne sont pas visibles. Une variable globale est au contraire visible partout. Par défaut les variables sont automatiques. Les variables statiques peuvent être utiles, mais on fait beaucoup mieux avec la programmation objet. Quant aux variables globales, on ne saurait trop déconseiller de les utiliser ! Variables automatiques Quand une variable est déclarée à l’intérieur d’une fonction (c’est-à-dire entre les {} qui définissent le corps de la fonction), elle n’est pas visible – autrement dit, on ne peut pas lire ni modifier sa valeur – de l’extérieur de la fonction. Par exemple, la variable nom est uniquement accessible aux instructions de la fonction MaFonc() dans l’exemple ci-dessous : MaFonc ( ) { $nom = "Vertigo"; } Le terme « automatique » vient de l’allocation automatique de l’espace nécessaire au stockage de la variable, chaque fois que la fonction est appelée. Conséquence très importante : le contenu de la variable automatique est perdu entre deux appels à une fonction. Ceci est tout à fait cohérent avec l’idée qu’une fonction effectue une tâche bien précise, utilisant pour cela des variables temporaires de travail. Variables statiques Il existe un second type de variable dite statique, qui présente les propriétés sui- vantes : 1. elle n’est pas visible à l’extérieur de la fonction où elle est déclarée ; 2. entre deux appels à une fonction, une variable statique conserve sa valeur (le terme « statique » vient du C, et signifie que l’emplacement en mémoire de la variable est constant). On peut par exemple définir une variable qui compte le nombre d’appels à une fonction. MaFonc ( ) { // On d´efinit la variable statique, et on l’initialise static $compteur = 0; 11.6 Fonctions 439 // On incr´emente la variable $compteur++; echo "Nombre d’appels `a MaFonc : " . $compteur; } Les variables statiques offrent moins de possibilités en PHP qu’en C. Elles sont souvent avantageusement remplacées par la programmation objet. Variables globales Par opposition aux variables automatiques, une variable globale est définie à l’ex- térieur de toute fonction, et rendue accessible à l’intérieur des fonctions grâce au mot-clé global. MaFonc () { // On d´efinit la variable globale global $nom ; $nom = "N’importe quoi"; } // Beaucoup de lignes de codes. $nom = "Vertigo"; MaFonc(); // La variable $nom contient "N’importe quoi" !!! La variable $nom peut être manipulée, de manière totalement transparente, par la fonction MaFonc(). Rien n’indique que la fonction modifie la variable (elle n’est même pas passée en argument). En pratique, l’utilisation des variables globales est à proscrire. Les inconvénients sont innombrables. 1. Manque de lisibilité : quand on voit un appel de fonction dans un programme, on pense naturellement que la fonction ne manipule que les données passées en paramètre. C’est faux si on utilise des variables globales. D’où une grande difficulté à comprendre le code. 2. Manque de sécurité : si vous définissez une variable globale, tout le monde peut y toucher ! Donc impossible de faire des contrôles sur le contenu de cette variable. Impossible même de garantir qu’une fonction anodine n’est pas en train de la modifier quand vous exécutez un programme qui a l’air sain. La variable globale, c’est l’effet de bord institutionalisé. 3. Manque d’évolutivité : on fige pour toujours le nom d’une information, ce qui est mauvais pour l’évolution d’un programme. Arrêtons là : on peut écrire une application de taille quelconque sans jamais utiliser de variable globale. Celà revient à donner la priorité aux fonctions sur les variables, et c’est un excellent principe. 440 Chapitre 11. Récapitulatif PHP 11.7 PROGRAMMATION ORIENTÉE-OBJET La programmation orientée-objet a considérablement évolué en PHP 5. Le chapitre 3 lui est entièrement consacré. Ce qui suit n’est donc qu’un rappel concis, complété des quelques fonctionnalités objets secondaires non évoquées dans le chapitre 3. Une classe est un ensemble d’attributs et de fonctions (le terme technique est méthodes) manipulant ces attributs. Une méthode n’est rien d’autre qu’une fonction s’exécutant au sein d’un objet, dont l’environnement est constitué de l’ensemble des attributs – ou propriétés,ouencorevariables d’état – constituant l’objet. Ces attributs sont accessibles au sein d’une méthode via la variable $this, qui désigne l’objet courant. La méthode accède à cet environnement, à ses propres paramètres, et à rien d’autre. 11.7.1 Classes et objets Les définitions des attributs et des méthodes sont rassemblées dans la structure class. Voici l’esquisse d’une définition de classe pour gérer des objets géométriques, avec deux méthodes. L’une, afficher(), pour afficher l’objet sur un écran, l’autre, surface(), pour calculer la surface de l’objet. Exemple 11.1 exemples/Geom.class.php : une classe d’objets géométriques <?php class Geom { // Partie priv´ee : les propri´et´es private $abcisses, $ordonnees; // Les coordonn´ees. private $nbPoints; // Nombre de points const PI = 3.14116; // Puis les m´ethodes public function ajoutPoint ($x, $y) { $this->abscisses[$this->nbPoints] = $x; $this->ordonnees[$this->nbPoints] = $y; $this->nbPoints++; } public function afficher ($ecran) { for ($i = 0; $i $<$ $this->nbPoints; $i++) $ecran->affiche($this->abcisses[$i], $this->ordonnees[$i]); } public function surface () { // Ici un calcul de surface return $surface; } } 11.7 Programmation orientée-objet 441 Les propriétés et fonctions peuvent être qualifiées par public, private ou protected. Tout ce qui est public est accessible librement par les instructions manipulant un objet, alors que tout ce qui est private n’est accessible que par lesméthodesdelaclasse.Lemot-cléprotected indique que seules les sous-classes peuvent accéder à la propriété ou à l’attribut (voir plus loin). On peut également associer des constantes à une classe, comme ici la constante PI avec sa valeur (qui ne change jamais !). On peut faire référence à cette constante interne avec la syntaxe Geom::PI (les constantes ne sont jamais privées en PHP). Une classe est une sorte de moule pour construire – on parle d’instanciation –des objets se conformant à sa définition. On utilise le constructeur new. $icone = new Geom; // Ajout de quelques points $icone->ajoutPoint(12, 43); $icone->ajoutPoint(32, 30); $icone->ajoutPoint(56, 6); // Calcul de la surface echo "Surface = " . $icone->surface(); Dès qu’un objet est instancié, il devient possible de lui appliquer les méthodes de sa classe. 11.7.2 Constructeurs et destructeurs Une méthode particulière, le constructeur, peut être utilisée pour initialiser les attri- buts d’un objet. Cette méthode doit porter soit le nom que la classe, soit le nom réservé __construct.VoicilaméthodeGeom() que l’on pourrait définir pour initialiser lesobjetsdelaclasseGeom. function Geom ($X, $Y, $pNbPoints) { $this->nbPoints = $pNbPoints; for ($i = 0; i < $pNbPoints; $i++) { $this->abcisses[$i] = $X[$i]; $this->ordonnees[$i] = $Y[$i]; } } Le constructeur prend en entrée un tableau d’abcisses, un tableau d’ordonnées, et le nombre de points. On peut alors appeler le constructeur avec new. $icone = new Geom (array (12, 32, 56), array (43, 30, 6), 3); // Calcul de la surface echo "Surface = " . $icone->surface(); On peut également définir un destructeur nommé __destruct. Il est appelé quand la dernière variable stockant une référence à un objet est détruite avec unset() (ou quand le script est terminé). 442 Chapitre 11. Récapitulatif PHP Quand on crée une sous-classe, le constructeur et le destructeur de la classe parente ne sont pas appelés automatiquement. C’est au programmeur de le faire, s’il le souhaite, avec la syntaxe parent::__construct() et parent::__destruct(). 11.7.3 Sous-classes On peut créer des sous-classes d’une classe. Les objets d’une sous-classe sont des objets de la classe parente, mais avec un comportement (ensemble d’attributs et de méthodes) plus détaillé et plus précis. Une sous-classe se définit avec le mot-clé extends. On peut par exemple définir des sous-classes Rectangle, Polygone,etc, pour la classe Geom. class Rectangle extends Geom { // Les attributs sont h´erit´es. function Rectangle ($X, $Y) { if (count($X) != 4 or count($Y) != 4) { echo "Un rectangle a quatre sommets !"; exit; } $this->Geom ($X, $Y, 4); } public function surface () { return ($this->abcisses[1] - $this->abcisses[0]) * ($this->ordonnees[1] - $this->ordonnees[0]); } } Comme un rectangle est un objet de la classe Geom,ilhérite de tous les atri- buts de cette classe (soit le tableau des abcisses et des ordonnées) et de toutes ses méthodes. Cependant un rectangle a une définition plus précise qu’un objet géométrique quelconque : il a quatre sommets, à angle droits. Le constructeur de la classe Rectangle doit tester que ces contraintes sont vérifiées (réalisé partiellement dans l’exemple ci-dessus) avant d’appeler le constructeur de Geom qui initialise les tableaux. De même, la méthode de calcul d’une surface est beaucoup plus facile à implan- ter pour un rectangle. On a donc remplacé la définition générale de la méthode surface() par une implantation plus spécifique que celle de la classe Geom.On parle de surcharge dans le jargon orienté-objet. 11.7.4 Manipulation des objets L’opérateur new renvoie une référence vers un objet instance de la classe. Toutes les manipulations d’un objet en PHP 5 s’effectuent ensuite par l’intermédiaire de . $this, qui désigne l’objet courant. La méthode acc de à cet environnement, à ses propres paramètres, et à rien d’autre. 11.7.1 Classes et objets Les définitions des attributs et des méthodes sont rassemblées. $this->ordonnees[0]); } } Comme un rectangle est un objet de la classe Geom,ilhérite de tous les atri- buts de cette classe (soit le tableau des abcisses et des ordonnées) et de toutes ses méthodes. Cependant un rectangle. peut créer des sous-classes d’une classe. Les objets d’une sous-classe sont des objets de la classe parente, mais avec un comportement (ensemble d’attributs et de méthodes) plus détaillé et plus