11.5 Structures de contrôle 433 On ne rentre dans la boucle que si la condition est vraie au départ. Il va sans dire qu’il doit y avoir dans la boucle au moins une instruction qui fait varier la valeur de expression de manière à ce que celle-ci devienne fausse après un nombre fini d’itérations. Une syntaxe légèrement différente du while marque le bloc à exécuter de manière différente. while (expression ): // expression est vraie. endwhile; Le do-while Le do-while est une variante du while qui effectue le bloc avant d’évaluer le test. En conséquence, ce bloc est toujours exécuté au moins une fois. do { // expression n’est pas forc´ement vraie au premier passage } while (expression ); Le for L’instruction for permet d’exécuter une itération sur une variable incrémentée (ou décrémentée) à chaque passage de la boucle. C’est la plus puissante des structures de boucle puisqu’on peut y spécifier • l’initialisation des valeurs conditionnant l’itération ; • la ou les instructions faisant évoluer ces valeurs à chaque passage ; • la condition d’arrêt de la boucle. Par exemple, considérons la partie de code suivante : $x=0; while ($x < 10) { // Ici des instructions $x++; // permet d’incr´ementer $x de 1. ´ Equivalent `a $x = $x+1 } Par construction, on passera 10 fois dans la boucle. On peut écrire cela plus concisément avec for : for ($x=0; $x < 10; $x++) { // Ici des instructions } Dans le for,lapremièrepartieinitialiselavariabledecontrôle(ici$x), la deuxième indique le test de fin, et la troisième effectue l’incrémentation. On peut 434 Chapitre 11. Récapitulatif PHP mettre des choses beaucoup plus compliquées : $a=1; $b=6; while ($a < $b) { $a++; echo "$a=".$a); } peut être remplacé par : for ($a=1,$b=6; $a < $b; $a++, echo "$a=".$a); On effectue donc une boucle for sur une instruction vide (’;’), les actions étant intégrées à l’instruction for elle-même. Ce mode de programmation très compact est apprécié de certains programmeurs, en particulier de ceux qui se font une gloire de produire un code court et illisible. Le foreach L’instruction foreach est conçue pour parcourir facilement un tableau. Il en existe deux formes, selon que le tableau est indicé ou associatif. foreach ($tableau as $valeur) { /* bloc */ } // Tableau indic´e foreach ($tableau as $cle => $valeur) { /* bloc */ } // Tableau associatif À chaque étape du parcours de $tableau, le curseur interne est incrémenté, et la valeur de l’élément courant (ainsi que la clé dans la seconde forme) est affectée à $valeur (ainsi qu’à $cle). 11.5.3 Les instructions break et continue En principe, quand on est dans le corps d’une boucle, toutes les instructions seront exécutées jusqu’à ce que le test qui détermine si on doit effectuer ou non une nouvelle itération soit évalué. Il existe deux instructions qui permettent d’obtenir un comportement plus souple. 1. break déclenche la sortie forcée de la boucle ; 2. continue dirige l’exécution à la prochaine évaluation du test de continua- tion, en sautant les éventuelles instructions complétant le corps de la boucle. Voici un exemple illustrant ces deux instructions. On effectue une boucle avec 10 itérations, mais au lieu de s’appuyer sur le mécanisme normal du while, on utilise break pour sortir de la boucle quand la variable de contrôle vaut 10. $x=0; while (1) { if ($x == 10) break; // $x vaut 10 ? On s’en va 11.6 Fonctions 435 $x++; // incr´emente $x de 1. ´ Equivalent `a $x = $x+1 if ($x != 5) continue; // $x diff´erent de5?Onsaute la suite // Ici les instructions pour le cas o`u $x vaut 5 } Noter le while (1) qui revient à effectuer une boucle à priori infinie. Le seul moyen de l’interrompre est alors le break,ouexit qui interrompt le script. L’instruction continue est déclenchée si la valeur de $x est différente de 5, ce qui revient à aller directement au while en ignorant la suite du corps de la boucle. Ces instructions sont valables également pour les variantes for et do. 11.6 FONCTIONS Les fonctions en PHP doivent être définies avant leur appel. Le nom d’une fonction ne commence pas par ’$’, et n’est pas sensible à la casse. Voici la syntaxe de définition d’une fonction. function NomFonction ([£arg1, £arg2, ]) { // Ici le code de la fonction } Une fonction peut prendre un nombre arbitraire, mais fixe de variables. Les fonctions avec un nombre variable d’arguments n’existent pas en PHP, mais on on peut contourner cette limitation en passant un tableau en paramètre 1 . Une fonction peut renvoyer une valeur avec l’instruction return, mais ce n’est pas indiqué dans sa signature. La valeur renvoyée peut être un tableau. function FilmVertigo () { return array ("Vertigo", "Alfred", "Hitchcock"); } // Appel de la fonction list ($titre, $prenom, $nom) = FilmVertigo (); 11.6.1 Passage des arguments Les arguments sont passés par valeur, ce qui signifie qu’une copie des variables est faite au moment de l’appel de la fonction, et que les éventuelles modifications faites dans le corps de la fonction sur les arguments n’ont qu’un effet local. Il existe une exception depuis la version 5 : les objets sont passés par référence. 1. Il existe cependant des techniques avancées pour gérer des listes de paramètres quel- conques : voir dans la documentation PHP les fonctions func_num_args(), func_get_args() et func_get_arg() si cela vous intéresse. 436 Chapitre 11. Récapitulatif PHP function Addition ($i, $j) { // NB : $i et $j sont des variables locales $somme = $i + $j; $i=2;$j=3; return $somme; } $i=1;$j=1; // Appel de la fonction $k = Addition ($i, $j); // $i et $j valent toujours 1 ! Le passage par valeur est préférable, parce qu’il signifie que toutes les actions de la fonction n’ont pas d’impact sur le script qui l’appelle. En conséquence, le script n’a pas à savoir comment la fonction est implantée et n’a pas à craindre des « effets de bord » indésirables. Il est cependant possible de passer des variables par référence. C’est alors l’adresse de la variable qui est transmise à la fonction, et pas une copie de sa valeur. Il existe deux manières d’indiquer un passage par référence : 1. au moment de l’appel, même pour une fonction qui a été prévue pour travailler sur des arguments passés par valeur ; 2. dans la définition de la fonction. C’est alors la règle par défaut pour tout appel de la fonction. La première option est très dangereuse et va probablement disparaître dans une prochaine version de PHP. Il faut l’éviter. La seconde méthode, avec des arguments explicitement prévus pour être passés par référence, rejoint une technique classique, et présente moins de dangers. Voici une version de la fonction Addition() qui prend en argument une troisième variable, passée par référence afin de stocker le résultat en sortie. function Addition ($i, $j, &$somme) { $somme = $i + $j; $i=2;$j=3; } $i=1;$j=1; // Appel de la fonction : $k est pass´ee par adresse Addition ($i, $j, $k); // $i et $j valent toujours 1, mais $k vaut 2 ! Un défaut de la syntaxe de PHP est qu’on ne peut pas savoir, en lisant un script, si les variables sont passées par valeur ou par adresse. Il est tout à fait possible de tout écrire sans recourir au passage par adresse, ce qui élimine toute ambiguïté. C’est le choix de tous les scripts présentés dans ce livre. Le seul inconvénient potentiel est un éventuel problème de performance si on passe des variables volumineuses (commme un gros tableau) par valeur : voir la discussion page 61 à ce sujet. 11.6 Fonctions 437 11.6.2 Valeurs par défaut Il est possible de définir des valeurs par défaut pour un ou plusieurs arguments d’une fonction. Cette idée, reprise du C++, s’avère très pratique quand on a beaucoup de paramètres dont la plupart prennent toujours la même valeur. Voici l’exemple d’une fonction de connexion, dont on suppose que dans la plupart des cas elle sera utilisée pour accéder à la base Films sur le serveur MonServeur.On précise donc ces valeurs par défaut. function Connexion ($pNom, $pMotPasse, $pBase = "Films", $pServeur = "MonServeur") { // Ici le corps de la fonction } Maintenant on peut éventuellement omettre les deux derniers paramètres en appelant la fonction. On peut aussi les donner, et dans ce cas on se ramène à un passage classique de paramètres. // Connexion `a la base Films, sur le serveur MonServeur $connexion1 = Connexion ("rigaux", "mdprigaux"); // Connexion `a une autre base, sur un autre serveur. $connexion2 = Connexion ("davy", "mdpdavy", "Films", "cartier"); On ne peut utiliser les valeurs par défaut que de droite à gauche dans la liste des arguments, et en commençant par le dernier. Il n’est pas possible par exemple, dans la fonction Connexion(), de donner une valeur par défaut au nom de la base et pas au serveur, à moins de modifier l’ordre des arguments. L’interpréteur doit toujours être capable de donner une valeur aux arguments non spécifiés au moment de l’appel. Le mot-clé unset peut être utilisé comme valeur par défaut. Dans ce cas l’argument correspondant n’est pas défini dans la fonction si cet argument n’est pas spécifié dans l’appel de la fonction. 11.6.3 Fonctions et variables Quand on programme, on manipule des variables et des fonctions. Quels sont les rapports entre les deux ? Où doit-on déclarer une variable ? Quel est son degré de visibilité par rapport aux fonctions et/ou aux scripts ? PHP propose trois types de variables (nous reprenons la terminologie du C). Variables automatiques. Ces variables sont créées dès que l’on entre dans leur espace de définition, qui est soit le script, soit une fonction¿; elles disparaissent quand on sort de cet espace. Variables statiques. Une variable automatique est détruite quand on quitte le corps d’une fonction, et sera recréée au prochain appel de la fonction. Sa valeur . fonction est implantée et n’a pas à craindre des « effets de bord » indésirables. Il est cependant possible de passer des variables par référence. C’est alors l’adresse de la variable qui est. si cet argument n’est pas spécifié dans l’appel de la fonction. 11.6.3 Fonctions et variables Quand on programme, on manipule des variables et des fonctions. Quels sont les rapports entre les deux. est faite au moment de l’appel de la fonction, et que les éventuelles modifications faites dans le corps de la fonction sur les arguments n’ont qu’un effet local. Il existe une exception depuis la version