IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Cours de PHP 5

Image non disponible


précédentsommairesuivant

III. Syntaxe du langage PHP

Afin de réduire la quantité de code pouvant parasiter la compréhension, dans cette page j'utiliserai principalement des scripts CLI.

III-A. Préambule

Cette partie est nécessaire mais tout lire assidûment dès le départ n'est peut-être pas la meilleure méthode pour apprendre PHP. Pour votre lecture, je vous propose de lire rapidement la syntaxe dans un premier temps, et de revenir à ces paragraphes au fur et à mesure que d'autres concepts apparaissent ou que vous avez des doutes syntaxiques.

Un bloc de code PHP est délimité par une balise d'ouverture <?php et une balise de fermeture ?>.

Un bloc de code PHP peut être le seul bloc de code dans le fichier, ou bien être mélangé à d'autres langages (par exemple HTML ou XML).

Création d'image (PHP pur) :
Sélectionnez
<?php
$image = imagecreatetruecolor(100, 50);
$text_color = imagecolorallocate($image, 255, 0, 0);
imagestring($image, 1, 5, 5, 'Hello, world!', $text_color);
header('Content-Type: image/png'); //type MIME
imagepng($image);
PHP incrusté dans du HTML :
Sélectionnez
<?php
/*
  Récupération des variables $title, $charset et $body
  par exemple depuis un formulaire ou une BDD
*/
header('Content-Type: text/html; charset='.$charset); //type MIME
?>
<?xml version="1.0" encoding="<?php echo $charset; ?>"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr-FR" lang="fr-FR">
<head>
    <title><?php echo $title; ?></title>
    <meta http-equiv="content-Type" content="text/html; charset=<?php echo $charset;?>" />
</head>
<body>
<?php echo $body; ?>
</body>
</html>

La balise de fermeture de code PHP ?> n'étant pas nécessaire lorsque le script se termine (tel que dans l'exemple d'image ci-dessus), nous l'utiliserons le moins possible. Cela permet d'éviter certaines erreurs, surtout en débutant. Elle est nécessaire uniquement si l'on souhaite alterner PHP et un autre langage.

III-B. Présentation du code

Vous pouvez varier la présentation du code source (ajouter des espaces, des tabulations et des sauts de ligne) sans que cela affecte l'exécution.

Une "instruction" est une portion de code se terminant par un point virgule (;). Par convention, on la représente sur une ligne de code propre.

 
Sélectionnez
<?php
echo "Hello World!";
echo "Je m'appelle Guillaume Rossolini";

L'indentation du code désigne l'utilisation des espaces et des tabulations pour structurer visuellement le code en niveaux. Cela ne change aucunement le résultat de l'exécution, mais facilite la relecture du code par un collaborateur ou par soi-même. Un code très mal indenté peut induire le programmeur en erreur et causer de grands dysfonctionnements lors d'opérations de maintenance.

Adrien Pellegrini vous propose ses conseils : Guide de style pour bien coder.

III-C. Parenthèses

Le code d'une instruction peut être groupé au moyen de parenthèses "()" afin de faciliter la lecture ou de forcer les priorités. PHP définit des priorités même s'il n'y a pas de parenthèses, mais il est parfois nécessaire de modifier les priorités imposées par le langage. Le principe est exactement le même qu'en mathématiques :

 
Sélectionnez
<?php
echo 1+2*3; //affiche "7"
echo (1+2)*3; //affiche "9"

Utilisez les parenthèses pour clarifier l'ordre dans lequel les opérations doivent avoir lieu, mais ne surchargez pas votre code pour autant. Ne mettre aucune parenthèse peut porter à confusion (tout le monde ne connaît pas par coeur la priorité de chacun des opérateurs) mais trop de parenthèses rend le code confus. Il faut donc trouver un équilibre.

III-D. Accolades

Les blocs d'instructions (une à plusieurs instructions) peuvent être identifiés par des accolades "{}". Dans d'autres langages, cela permet de limiter la portée (scope) d'une variable, mais en PHP cet effet n'est pas pris en compte.

En revanche, les accolades définissent la portée d'une structure de contrôle (cf. plus loin) et les limites du corps d'une fonction.

 
Sélectionnez
<?php
function additionner($x, $y)
{
    //nous sommes dans le corps de la fonction "additionner"
    return $x + $y;
}

//ici, nous ne sommes plus dans le corps de la fonction "additionner"

Les accolades sont facultatives dans certaines situations (par exemple s'il n'y a qu'une seule instruction dans un "if") mais je vous recommande de systématiquement les mettre, car cela ne prend pas beaucoup de temps alors que la valeur ajoutée est très grande (lisibilité du code).

III-E. Commentaires

Les commentaires en PHP permettent d'introduire des sections de texte qui ne sont pas exécutées. L'utilisation principale est pour la maintenance, l'évolution du code, afin de permettre au développeur d'introduire des commentaires explicites sur ses intentions.

Ils prennent généralement deux formes :

 
Sélectionnez
<?php
//Commentaire sur une ligne
 
Sélectionnez
<?php
/*
Commentaire sur plusieurs lignes
*/

Il existe également une forme avec un caractère dièse (#) au lieu du double slash (//), mais cette syntaxe n'est pas conseillée car ce type de commentaire est moins courant parmi les langages de programmation. Sachez simplement qu'elle existe afin de ne pas vous étonner de la voir des scripts écrits par d'autres personnes.

Le commentaire // est parfois utilisé en fin d'instruction pour expliquer son utilité.
Le commentaire /* */ est extensivement utilisé par les générateurs de documentation automatique de code.

 
Sélectionnez
<?php

/**
 * Chien
 *
 * @author Yogui
 * @copyright Guillaume Rossolini (c) 2007
 * @version 8.12.2007
 * @access public
 */
class Chien
{
    private $âge; //en années

    /**
     * Chien::__construct()
     *
     * @param int $âge
     */
    public function __construct($âge)
    {
        $this->âge = (int)$âge;
    }
}

III-F. Opérateurs

III-F-1. Arithmétique (+ - * / %)

PHP dispose des opérateurs classiques pour effectuer des calculs :

Addition
Sélectionnez
<?php
echo 1+1; //addition
echo 1-1; //soustraction
echo 1*1; //multiplication
echo 1/1; //division
echo 1%1; //modulo (reste de la division)

III-F-2. Affectation de variable (= += -= *= /= .=)

Les opérateurs d'affectation permettent de donner une valeur à une variable.

Valeurs numériques :
Sélectionnez
<?php
$x = 5;
$x += 1; //ajoute à la valeur existante
$x -= 2; //soustrait à la valeur existante
$x *= 3; //multiplie la valeur existante
$x /= 4; //divise la valeur existante
echo $x; //affiche "3"
Chaînes :
Sélectionnez
<?php
$str = 'texte';
$str .= ' additionnel'; //concatène à la suite de la chaîne existante
echo $str; //affiche "texte additionnel"

III-F-3. Comparaison (== === != <> !== > >= < <= instanceof)

L'opérateur "==" est un opérateur de comparaison de valeurs. Il ne tient pas compte du type de la valeur, puisque PHP est un langage à typage faible. L'opérateur "!=" est l'inverse de "==".

 
Sélectionnez
<?php
echo 1==1; //affiche "1"
echo 1==2; //n'affiche rien puisque c'est faux
echo 1==1.0; //affiche "1" puisque ce sont deux valeurs entières équivalentes
echo '1'==1.0; //affiche "1" puisque la chaîne "1" est équivalente à l'entier numérique "1"
echo '1'=='1.0'; //affiche "1" puisque leur valeur numérique évalue à la même valeur entière

L'opérateur "===" est le même que le précédent, sauf qu'il n'effectue pas de conversion de type. Il est donc plus rapide que l'opérateur "==" et il ne donne pas les mêmes résultats. L'opérateur "!==" est l'inverse de "===".

 
Sélectionnez
<?php
echo 1===1; //affiche "1" puisque les deux valeurs sont identiques en valeur et en type
echo 1===2; //n'affiche rien puisque c'est faux
echo 1===1.0; //n'affiche rien puisque le type diffère (int et float)
echo '1'===1.0; //n'affiche rien puisque le type diffère (string et float)
echo '1'==='1.0'; //n'affiche rien puisque les deux chaînes ne sont pas égales
Voir également :

Les opérateurs "<>" et "!=" sont identiques, ils permettent à des développeurs issus de différents horizons de s'adapter sans problème à PHP. Ils fonctionnent aussi bien pour les nombres que pour les chaînes.

Les opérateurs "<", ">", "<=" et ">=" sont assez classiques pour ne pas nécessiter d'explications. Ils fonctionnent aussi bien pour les nombres que pour les chaînes.

L'opérateur instanceof permet de comparer les classes :

 
Sélectionnez
<?php
if($objet instanceof MaClasse) //attention, ne pas mettre le nom de classe entre guillemets
{
    echo 'même classe ou classe fille';
}

if($objet_1 instanceof $object_2)
{
    echo 'même classe ou classe fille';
}

L'opérateur instanceof fonctionne également avec les classes héritées et avec les interfaces.

III-F-4. Condition (?)

L'opérateur ternaire "?" est une alternative : "est-ce vrai ? valeur si oui : valeur sinon".

 
Sélectionnez
<?php
echo 1==1 ? 'vrai' : 'faux'; //affiche "vrai"
echo 1==2 ? 'vrai' : 'faux'; //affiche "faux"

On utilise souvent les parenthèses pour faciliter la lecture de cet opérateur.

 
Sélectionnez
<?php
echo (1==1) ? 'vrai' : 'faux';
echo (1==2) ? 'vrai' : 'faux';

Cet opérateur est plus lent à l'exécution qu'une structure conditionnelle if/else (cf. nos benchmarksTests et benchmarks en PHP 5). De plus, il peut rendre le code illisible s'il est utilisé trop souvent ou dans des instructions trop longues. Il est donc à utiliser avec précaution, et exclusivement dans des instructions très courtes (notamment sans appel de fonction).

Cet opérateur peut, sous certaines conditions, être utilisé pour affecter des variables. L'exemple qui suit montre un exemple d'affectation (sécurisée et sans erreur) de la variable $id :

 
Sélectionnez
<?php
//la valeur entière de $_GET['id'] ou zéro si la variable n'existe pas
$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;

Depuis PHP 5.3 et 6.0, il existe une alternative abrégée :

 
Sélectionnez
<?php
$id = $_GET['id'] ?: 0; //$_GET['id'] ou zéro si la variable est vide

Le problème de cette dernière approche est que dans de très nombreuses situations, elle met le script en danger. Dans l'exemple ci-dessus par exemple, nous n'effectuons aucune vérification sur le type ou le contenu de la variable... Il convient donc d'utiliser la version abrégée de l'opérateur ternaire uniquement dans des situations parfaitement maîtrisées. De plus, écrire par exemple "echo isset($_GET['id']) ?: 0;" n'aurait aucun sens, ce qui peut facilement causer des alertes E_NOTICE.

III-F-5. Incrémentation / diminution (++ --)

  • ++ : Augmenter de 1 ;
  • -- : Diminuer de 1.
 
Sélectionnez
<?php
$x = 5;
echo ++$x; //incrémente puis affiche 6
echo $x; //affiche 6

$x = 5;
echo $x++; //affiche 5 puis incrémente
echo $x; //affiche 6

$x = 5;
echo --$x; //réduit puis affiche 4
echo $x; //affiche 4

$x = 5;
echo $x--; //affiche 5 puis réduit
echo $x; //affiche 4

Ces opérateurs fonctionnent également avec les chaînes.

III-F-6. Arithmétique logique, aka opérateurs de bits (& |)

Ces opérateurs permettent d'effectuer des opérations de bits, très utilisées par exemple pour les variables de configuration. Les opérations logiques sont bien plus rapides que les opérations décimales, il peut donc dans certains cas être intéressant de les utiliser.

Les opérateurs ayant un équivalent ensembliste :
  • & (and) : Équivalent à une intersection d'ensembles (les bits à 1 dans les deux ensembles donnent 1, les autres donnent 0) ;
  • | (or) : Équivalent à une union d'ensembles ("ou" inclusif : les bits à 1 dans au moins l'un des ensembles donnent 1, les autres donnent 0) ;
  • ^ (xor) : Équivalent à une union d'ensembles ("ou" exclusif : les bits à 1 dans exactement l'un des ensembles donnent 1, les autres donnent 0) ;
 
Sélectionnez
<?php
echo 0&0; //affiche "0"
echo 0&1; //affiche "0"
echo 1&1; //affiche "1"

echo 0|0; //affiche "0"
echo 0|1; //affiche "1"
echo 1|1; //affiche "1"

echo 0^0; //affiche "0"
echo 0^1; //affiche "1"
echo 1^1; //affiche "0"
 
Sélectionnez
<?php
echo 1&5; //affiche "1"
echo 1|5; //affiche "5"
echo 1^5; //affiche "4"

Si on calcule l'union des équivalents binaires de 1 et 4 (soit "un ou quatre inclusif"), on obtient l'équivalent de 5 :

 
Sélectionnez
001
100 |
101 =
 
Sélectionnez
<?php
echo 1|4; //affiche "5"

L'union de 4 et 5 vaut également 5 :

 
Sélectionnez
100
101 |
101 =
 
Sélectionnez
<?php
echo 4|5; //affiche "5"

En revanche, par la différence logique de 1 et 4 (soit "un et quatre"), on obtient 0 :

 
Sélectionnez
001
100 &
000 =
 
Sélectionnez
<?php
echo 1&4; //affiche "0"

Mais l'intersection de 4 et 5 vaut 4 :

 
Sélectionnez
100
101 &
100 =
 
Sélectionnez
<?php
echo 4&5; //affiche "4"

C'est par exemple cette méthode qui est utilisée pour le niveau d'erreurs géré par PHP (directive error_reporting du fichier php.ini).

Les autres opérateurs de bits :
  • ~ $x : Inversion du positionnement des bits dans $x (not) ;
  • $x << $n : $x est multiplié $n fois par 2 (décalage à gauche) ;
  • $x >> $n : $x est divisé $n fois par 2 (décalage à droite).

Une manière optimisée d'effectuer des divisions ou des multiplications par 2 est d'utiliser le décalage de bits. Cependant, cela ne peut fonctionner que sous certaines conditions, par exemple se limiter à des nombres de 32 bits pour les systèmes 32 bits.

III-F-7. Comparaison logique (&& || and or)

Comme dans tout langage de programmation, ces opérateurs permettent de vérifier plusieurs conditions à la fois dans un même test. On peut écrire les opérateurs "and" et "or" en minuscules ou en majuscules.

 
Sélectionnez
<?php
if($variable > 2 and $variable < 10)
{
    echo 'valeur entre 2 et 10 (exclus)';
}
 
Sélectionnez
<?php
if($variable > 2 && $variable < 10)
{
    echo 'valeur entre 2 et 10 (exclus)';
}
 
Sélectionnez
<?php
if($variable > 2 or $variable < 10)
{
    echo 'valeur supérieure à 2 ou inférieure à 10 (exclus)';
}
 
Sélectionnez
<?php
if($variable > 2 || $variable < 10)
{
    echo 'valeur supérieure à 2 ou inférieure à 10 (exclus)';
}
  • "&&" et "and" sont identiques sauf pour la priorité qui leur est attribuée ;
  • "||" et "or" sont identiques sauf pour la priorité qui leur est attribuée.

Ma recommandation est d'utiliser "and" et "or" (au détriment de && et ||) puisqu'ils portent la sémantique en eux et qu'ils ne prêtent pas à confusion avec les opérateurs de bits.

Il s'agit d'opérateurs dits "paresseux" : avec l'opérateur "or", une seule condition vraie dans la liste permet d'avérer l'ensemble de l'instruction ; avec "and", une seule condition fausse dans la liste permet de refuser l'ensemble de l'instruction.

Démonstration de leurs priorités respectives :
Sélectionnez
<?php
//différence entre "&&" et "and"
var_dump(0 and 0 || 1); // FALSE car équivalent à : 0 and (0 or 1)
var_dump(0 && 0 || 1); // TRUE car équivalent à : (0 and 0) or 1

//différence entre "||" et "or"
var_dump(1 or 0 and 0); // TRUE car équivalent à : 1 or (0 and 0)
var_dump(1 || 0 and 0); // FALSE car équivalent à : (1 or 0) and 0

III-F-8. Opérateurs de tableaux (+ == === <> != !==)

C'est le même principe que les opérateurs antérieurs, mais avec les tableaux :
  • "+" : Union de tableaux ;
  • "==" : Les mêmes paires clef/valeur ;
  • "===" : Les mêmes paires clef/valeur, dans le même ordre et de même type ;
  • "<>" ou != : Au moins une paire clef/valeur ne correspond pas ;
  • !== : Au moins un triplet clef/valeur/type ne correspond pas.

III-F-9. Opérateurs spéciaux (@ ``)

L'arobase @ sert à contrôler l'affichage des erreurs. L'utiliser est considéré comme une mauvaise pratique, car cela suppose que votre code n'est pas sécurisé, qu'il ne fait pas les contrôles nécessaires. Par ailleurs, cet opérateur empêche PHP d'enregistrer l'erreur dans un fichier de log (errors.log), ce qui vous oblige à enregistrer vous-même l'erreur dans un log, ce qui finalement ne fait pas gagner de temps et ne simplifie pas le code. De plus, il faut activer une certaine directive de configuration pour avoir accès aux messages d'erreur si on utilise cet opérateur.

Rappel : Vous devriez toujours garder un log des erreurs. Consultez le log de temps en temps pour améliorer la sécurité de votre serveur et de vos applications.

L'opérateur "apostrophe arrière `" (ou "accent grave") permet d'exécuter une commande système (shell). Utiliser cet opérateur revient à utiliser la fonction shell_exec(), qui est moins intéressante que la fonction exec() de par le manque de paramètres.

III-G. Types

III-G-1. Préambule

Dès l'école primaire, on nous apprend à ne pas additionner des choux avec des carottes lorsque l'on apprend les "unités" en mathématiques. Les "types" sont exactement la même chose en programmation, ils ne sont pas nécessairement compatibles entre eux. Il existe cependant des moyens de convertir un type en un autre, tout comme on peut convertir des grammes en kilogrammes.

Un type définit une valeur, il permet de savoir comment on doit la traiter. PHP ne doit pas, ne peut pas traiter de la même manière un nombre et du texte, tout comme des litres et des grammes ne peuvent pas être utilisés de la même manière. Par exemple, additionner deux nombres est une opération mathématique, tandis qu'additionner des ensembles de valeurs revient à trouver leur union (ensemble des deux). La même opération ne doit pas être effectuée de la même façon sur deux types différents.

Les types sont définis à la fois pour aider le programmeur à connaître les données qu'il manipule (sécurité) et pour optimiser la gestion de la mémoire par l'interpréteur PHP. Il convient donc de connaître les différents types disponibles en PHP. Nous reviendrons plus loin sur leurs utilisations.

Les types PHP sont :
  • boolean : un contraste "vrai" ou bien "faux", "blanc" ou "noir", "1" ou "0", "yin" ou "yang"... ;
  • integer : une valeur numérique entière ;
  • double : une valeur numérique flottante (à virgule) ;
  • string : une chaîne de caractères (texte) ;
  • array : un tableau (ensemble de valeurs) ;
  • object : un objet (instance de classe) ;
  • resource : une ressource (type abstrait, inutilisable par le programmeur, utilisé uniquement pour des fonctions) ;
  • NULL : un type spécial qui désigne l'absence de valeur.

PHP est un langage à types dynamiques. Cela signifie que l'on ne peut pas définir de manière fixe le type d'une variable pour toute la durée de l'exécution du script ; au contraire, on parle de type juggling, à savoir qu'une variable peut changer de type selon les besoins (cf. exemples plus loin).

III-G-2. Type chaîne de caractères (string)

La chaîne de caractères est le moyen classique pour désigner du texte en programmation.

Dans de nombreux langages de programmation (ainsi qu'en bases de données), il faut déclarer la longueur de la chaîne (nombre de caractères dans le texte) avant d'affecter du texte à une variable. PHP reste cependant très flexible dans la gestion de la mémoire, cette déclaration n'est donc ni utile ni possible ici.

Une chaîne de caractères peut s'écrire de diverses manières en PHP, chacune utilisant un "délimiteur" bien précis :

 
Sélectionnez
<?php
//Délimitation par des guillemets :
echo "Hello World!";

//Délimitation par des apostrophes :
echo 'Hello World!';

//Délimitation par la syntaxe HereDoc :
$string = <<<END
Hello World!
END;
echo $string;

//Délimitation par la syntaxe NowDocs :
$string = <<<'END'
Hello World!
END;
echo $string;


//Caractère $ avec la syntaxe HereDoc :
$string = <<<END
Le signe \$ doit être échappé : \$var
END;
echo $string;

//Caractère $ avec la syntaxe NowDocs :
$string = <<<'END'
Le signe $ peut être utilisé : $var
END;
echo $string;

Les deux premières formes sont les plus communes. La 3° (HereDoc) est très largement moins utilisée à cause de sa complexité, ce qui est dommage car elle offre certains avantages. La 4° (NowDocs) est encore en discussion pour PHP 5.3.

La syntaxe des guillemets permet d'utiliser sans crainte les apostrophes, mais tout se complique dès que l'on souhaite utiliser des guillemets :

 
Sélectionnez
<?php
echo "Voici un exemple d'apostrophe";
echo "Voici un exemple de \"guillemets\"";

La syntaxe des apostrophes permet d'utiliser des guillemets dans le texte, mais nous ennuie avec les apostrophes :

 
Sélectionnez
<?php
echo 'Voici un exemple de "guillemets"';
echo 'Voici un exemple d\'apostrophe';

Si l'on souhaite pouvoir utiliser à la fois des guillemets et des apostrophes dans un même texte, plusieurs solutions s'offrent à nous :

Par échappement :
Sélectionnez
<?php
echo "Voici un exemple d'apostrophe suivi de \"guillemets\"";
Par échappement :
Sélectionnez
<?php
echo 'Voici un exemple d\'apostrophe suivi de "guillemets"';
HereDoc :
Sélectionnez
<?php
echo <<<EOT
Voici un exemple d'apostrophe suivi de "guillemets"
EOT;
Concaténation :
Sélectionnez
<?php
echo "Voici un exemple d'apostrophe" . ' suivi de "guillemets"';

Charge à chaque développeur de voir la syntaxe qui l'intéresse le plus pour déclarer une chaîne.

Les différences entre les délimiteurs de chaînes (guillements ou apostrophes) a été évoquée plus en profondeur par Pierre-Baptiste Naigeon : Apostrophes ou guillemets : lesquels choisir ?

Le point permet de concaténer des chaînes, c'est-à-dire de les ajouter les unes à la suite des autres. L'opérateur de concaténation n'est disponible que pour les chaînes de caractères, il ne l'est pour aucun autre type. Bien entendu, un point situé à l'intérieur des délimiteurs n'est pas un opérateur de concaténation mais un simple point, il faut qu'il soit positionné entre deux chaînes pour qu'il joue le rôle d'opérateur.

Il existe également une syntaxe à base d'accolades pour accéder aux caractères d'une chaîne : echo $string{8}; affiche le caractère de $string à la position 8 (c'est-à-dire le 9° caractère).

 
Sélectionnez
<?php
$user = 'Yogui';
echo $user; //affiche "Yogui"
echo $user[2]; //affiche "g" : gestion de la variable comme d'un tableau de caractères
echo $user{2}; //affiche "g" : gestion de la variable comme d'une chaîne (string)
echo substr($user, 2, 1); //affiche "g"

Les chaînes doivent toujours être traitées de manière spécifique, au cas par cas. Par exemple lors de l'affichage dans une page Web, il faut leur appliquer htmlentities() avant echo. Quelle que soit la destination de la chaîne, prenez soin de toujours appliquer la fonction de conversion adaptée.

III-G-3. Type numérique (int, float)

En PHP, il n'y a pas toujours de distinction entre "entier" et "flottant". Plus précisément, PHP effectue des changements de type selon la nécessité :

Test de types :
Sélectionnez
<?php
echo 1.2;
echo 1.0;
 
Sélectionnez
1.2
1

Cependant, le type est conservé :

Test de types :
Sélectionnez
<?php
var_dump(1.2);
var_dump(1.0);
var_dump(1);
 
Sélectionnez
float(1.2)
float(1)
int(1)

Il existe quelques subtilités au sujet des nombres à virgule flottante. L'article suivant permet d'éclaircir certains détails : http://docs.sun.com/source/806-3568/ncg_goldberg.html

III-G-4. Types spéciaux (null resource object)

  • NULL : Valeur/variable vide ou inexistante ;
  • resource : Par exemple une variable permettant d'identifier une connexion à une base de données ;
  • object : Utilisé en Programmation Orientée Objet (POO, cf. plus loin).
Ressource fichier :
Sélectionnez
<?php
$file = fopen(__FILE__, 'r');
echo $file;
var_dump($file);
fclose($file);
 
Sélectionnez
Resource id #3
resource(3) of type (stream)
Ressource objet :
Sélectionnez
<?php
var_dump(new stdClass());
 
Sélectionnez
object(stdClass)#1 (0) { }

III-G-5. Fonctions utiles

La fonction var_dump() affiche le type d'une variable et son contenu (ainsi que sa taille si c'est une chaîne). Elle s'applique aussi bien aux variables scalaires qu'aux objets, tableaux, ressources...

Texte :
Sélectionnez
<?php
var_dump("Voici du texte...");
 
Sélectionnez
string(17) "Voici du texte..."
Flottant :
Sélectionnez
<?php
var_dump(1.2);
 
Sélectionnez
float(1.2)
Flottant assimilable à un entier :
Sélectionnez
<?php
var_dump(1.0);
 
Sélectionnez
float(1)
Entier :
Sélectionnez
<?php
var_dump(1);
 
Sélectionnez
int(1)

La fonction gettype() permet de déterminer le type d'une valeur, ou get_resource_type() si c'est une ressource. Il existe également une fonction is_*() spécifique pour chaque type.

Déterminer le type :
Sélectionnez
<?php
echo gettype($variable); //affiche le type de la variable
echo get_resource_type($variable); //affiche le type de la ressource
Valeurs de retour possibles pour gettype() :
  • boolean
  • integer
  • double
  • string
  • array
  • object
  • resource
  • NULL

La fonction settype() permet de modifier le type d'une variable pendant l'exécution du programme. Des fonctions spécifiques intval(), floatval() et strval() permettent d'effectuer la même opération, et il est possible d'appliquer des "cast" à la mode du langage C.

Fonction settype() :
Sélectionnez
<?php
$x = 5.2;
var_dump($x);
settype($x, 'int');
var_dump($x);
 
Sélectionnez
float(5.2)
int(5)
Fonctions spécifiques :
Sélectionnez
<?php
var_dump(intval('5.2 ans'));
var_dump(floatval('5.2 ans'));
var_dump(strval('5.2 ans'));
 
Sélectionnez
int(5)
float(5.2)
string(7) "5.2 ans"

On appelle "transtypage" l'opération qui consiste à modifier le type d'une valeur de manière ponctuelle. Cela permet par exemple d'obtenir la valeur entière d'un nombre à virgule, ou bien au contraire de considérer comme un nombre entier comme étant un nombre à virgule.

Transtypage :
Sélectionnez
<?php
var_dump((int) 5.2);
var_dump((bool) 5.2);
var_dump((float) 5);
var_dump((string) 5.2);
var_dump((array) 5.2);
var_dump((object) 5.2);
 
Sélectionnez
int(5)
bool(true)
float(5)
string(3) "5.2"
array(1) {
  [0]=>
  float(5.2)
}
object(stdClass)#1 (1) {
  ["scalar"]=>
  float(5.2)
}
Valeurs possibles pour settype() :
  • bool
  • int
  • float
  • string
  • array
  • object
  • null

Les paramètres possibles de settype() et les retours possibles de gettype() sont différents pour des raisons historiques de l'évolution du langage.

III-H. Variables

III-H-1. Syntaxe

Une variable PHP est identifiée par le signe dollar ($) suivi d'une lettre puis d'une suite de lettres, chiffres et traits soulignés (_).

Par convention, un nom de variable ne commence pas par une majuscule. S'il faut plusieurs mots pour composer le nom, ils sont habituellement séparés par des soulignés (_).

Exemples :
Sélectionnez
<?php
$variable; //ok
$variable_2; //ok
$Variable; //ok mais pas conventionnel (majuscule)
$2; //nom incorrect
$2 */-+$% = 'essai'; //nom incorrect
Le nom d'une variable est sensible à la casse :
Sélectionnez
<?php
$var = 1;
$Var = 2;

// $var et $Var sont deux variables distinctes :
echo $var; //affiche "1"
echo $Var; //affiche "2"

Il existe d'autres manières de construire des noms de variables (en particulier des noms illégaux) mais, lorsqu'un tel besoin se fait sentir, il est souvent préférable d'utiliser des tableaux (nous y reviendrons par la suite).

Variable dynamique :
Sélectionnez
<?php
//exemple correct mais à éviter :
${'1 */-+$%'} = 'essai'; //ce qui est entre accolades est le nom de la variable
var_dump(${'1 */-+$%'}); //ok

//alternative à éviter aussi :
$index = '1 */-+$%';
${$index} = 'essai'; //le nom de variable correspond ici au contenu de "$index"
var_dump(${$index}); //ok

Contrairement à d'autres langages, il n'est pas nécessaire de déclarer une variable avant de pouvoir lui affecter une valeur. Cependant, prenez garde à ne pas utiliser la valeur d'une variable avant d'être certain de lui avoir effectivement donné une valeur car cela lancerait un avertissement.

Code incorrect :
Sélectionnez
<?php
echo $x; //PHP lance un avertissement puisque $x n'existe pas encore
Code ok :
Sélectionnez
<?php
$x = 3; //la première affectation sert de déclaration
echo $x;

Le type d'une variable PHP peut changer au cours de l'exécution d'un même script. Pour cela, il suffit de lui affecter une nouvelle valeur.

Exemple :
Sélectionnez
<?php
$variable = 1;
var_dump($variable);

$variable = 1.1;
var_dump($variable);

$variable = 'texte';
var_dump($variable);

$variable = new stdClass();
var_dump($variable);
 
Sélectionnez
int(1)
float(1.1)
string(5) "texte"
object(stdClass)#1 (0) {
}

Les variables ne sont visibles (scope) que dans le bloc dans lequel elles sont déclarées. Une variable déclarée dans une fonction, classe ou méthode n'est pas visible en-dehors de cette fonction, classe ou méthode.

III-H-2. Superglobales

Les variables superglobales sont mises en place par PHP lors du début du traitement d'une demande par Apache.

Ces variables n'obéissent pas aux limites habituelles des variables en termes de visibilité à l'intérieur d'une fonction. Elles sont accessibles de partout, c'est pourquoi elles portent le nom de "superglobales".

Voici les superglobales :
  • $_GET : Les valeurs provenant de l'URL ;
  • $_POST : Les valeurs envoyées par formulaire ;
  • $_FILE : Les fichiers envoyés par formulaire ;
  • $_SERVER : Les valeurs mises en place par le serveur Web (elles peuvent donc changer d'une configuration à l'autre) ;
  • $_ENV : Les variables d'environnement (système d'exploitation) ;
  • $_SESSION : Les valeurs mises dans le magasin des sessions ;
  • $_COOKIE : Les valeurs transmises au moyen de cookies par le navigateur ;
  • $GLOBALS : L'ensemble des variables du script.

Du point de vue de la sécurité, aucune de ces variables ne devrait être introduite telle quelle dans un script PHP, car elles sont toutes potentiellement modifiables par l'internaute. Cela signifie que l'internaute peut pirater nos scripts par l'intermédiaire de toutes ces variables, il faut donc les filtrer et les valider à chaque utilisation. Nous reviendrons plus loin sur les méthodes permettant d'y parvenir.

III-H-3. Références

Transmettre une variable en "entrée-sortie" à une fonction s'apparente à la passer par référence. En PHP5, il n'y a qu'une manière de faire :

 
Sélectionnez
<?php
$i = 0;
increment($i);
increment($i);
increment($i);
increment($i);

echo $i; //affiche "4"


function increment(&$nb)
{
    ++$nb;
}

Cette approche est très efficace en utilisation de mémoire, car elle évite à la fonction de recopier la valeur de ses paramètres transmis par référence. En revanche, il faut faire très attention lorsque l'on modifie ces valeurs, car les changements sont répercutés dans le scope appelant la fonction...
Nous verrons plus loin que les objets PHP5 sont systématiquement transmis par référence.

III-H-4. Fonctions utiles

L'affichage du contenu d'une variable se fait généralement au moyen de la fonction echo ou bien print, selon le choix du programmeur. Ces deux fonctions agissent presque de la même manière. Pour leur part, les fonctions var_export(), print_r() et var_dump() sont utiles principalement pour le débogage des scripts.

Affichage :
Sélectionnez
<?php
$x = 5;
echo $x; //affichage de la valeur
print $x; //affichage de la valeur
var_export($x); //affichage de la représentation PHP
print_r($x); //affichage du contenu
var_dump($x); //affichage du type et du contenu
Test d'existence :
Sélectionnez
<?php
if(isset($variable))
{
    //la variable existe
}
else
{
    //la variable n'existe pas
}
Test de nullité :
Sélectionnez
<?php
if(empty($variable))
{
    //la variable est nulle
}
else
{
    //la variable est non nulle
}
Destruction :
Sélectionnez
<?php
unset($variable);

Contrairement à echo, les constructs isset() et empty() ne lancent aucun avertissement si la variable n'existe pas.

III-H-5. Bonnes pratiques

Utilisez des noms de variable ayant du sens. Évitez les abréviations, les initiales, etc.

Évitez les noms du style "cas particulier", par exemple pour une couleur il faut éviter de décrire le contenu ($blue, $green...) et préférer la description de l'utilité de chaque variable : $row_color, $background_color... Appeler une variable en fonction de sa valeur revient à dupliquer les informations, ce qu'il faut toujours éviter de faire en programmation.

Si vous devez utiliser une syntaxe complexe pour afficher une variable, comme par exemple ce qui est dans la documentation officielle de PHP, préférez la concaténation ou l'utilisation de sprintf() :

À éviter :
Sélectionnez
echo "Ceci fonctionne : {$arr['foo'][3]}";
Ceci est préférable :
Sélectionnez
echo "Ceci fonctionne : " . $arr['foo'][3];
Meilleure solution :
Sélectionnez
echo sprintf("Ceci fonctionne : %s", $arr['foo'][3]); //préciser le type correct à la place de "%s"

III-I. Constantes

III-I-1. Syntaxe

Une constante est un nom qui permet de donner une sémantique à une valeur. Cette valeur est figée pour toute la durée de l'exécution du script PHP. Par convention, on exclut les lettres minuscules dans le nom d'une constante.

Déclaration :
Sélectionnez
<?php
define('NOM_ADMIN', 'Yogui'); //constante de type string
define('MAX_LIGNES', 5); //constante de type entier

L'utilisation des constantes est similaire à des variables. La différence est qu'il ne faut pas utiliser le signe dollar ($) car il s'applique uniquement aux variables. Par ailleurs, il ne faut pas utiliser "=" pour affecter une valeur à une constante, mais uniquement "define". Une fois que la valeur d'une constante est définie, elle ne peut plus être modifiée jusqu'à la fin du script.

 
Sélectionnez
<?php
define('NOM_ADMIN', 'Yogui');
echo NOM_ADMIN; //remarquez l'absence de guillemets et de signe dollar

Par convention, les noms des constantes sont écrits en lettres majuscules et en chiffres. S'il faut mettre plusieurs mots dans le même nom de constante (comme ci-dessus), on démarque chaque mot par un underscore.

Les constantes sont très utiles pour les valeurs de configuration qui ne doivent pas changer durant toute l'exécution d'un script, car elles nous assurent que la valeur ne sera modifiée à aucun moment de l'exécution.

Exemple d'utilisation incorrecte (erreur PHP) :
Sélectionnez
1.
2.
3.
<?php
define('MAX_LIGNES', 3);
define('MAX_LIGNES', 5);
 
Sélectionnez
Notice: Constant MAX_LIGNES already defined in C:\Web\online\http\tests\error.php on line 3

Un aspect intéressant des constantes est que, si l'on utilise une constante qui n'est pas définie, PHP envoie une alerte mais n'arrête pas le script : il utilise le nom de la supposée constante comme sa valeur. Il est évident qu'il faut éviter ce genre de situation, mais cela vaut la peine de le savoir.

Les constantes ne sont pas limitées en termes de visibilité (scope). Une fois déclarée, une constante est visible depuis toutes les fonctions et toutes les classes.

 
Sélectionnez
<?php

$user = 'Yogui';
define('USER', 'Yogui');

function test()
{
    echo $user; //lance un avertissement PHP "Undefined variable: user"
    echo USER; //ok
}


//lancemant de la démonstration
test();

III-I-2. Constantes magiques

Il existe des "constantes magiques" qui n'obéissent pas totalement aux règles des constantes. Elles existent dans tous les scripts sans qu'il soit nécessaire de les déclarer par programmation. On ne peut bien entendu pas les modifier par programmation, néanmoins leur valeur peut changer au fil de l'exécution du script. De plus, on peut les appeler indifféremment en majuscules ou en minuscules. Chacune de ces constantes contient une valeur qui change selon le contexte dans lequel elle est appelée.

  • __LINE__ : La ligne de code en cours ;
  • __FILE__ : Le nom complet du script en cours ;
  • __DIR__ : Le nom du répertoire du script en cours (depuis les versions 5.3 et 6.0 de PHP) ;
  • __FUNCTION__ : La fonction en cours ;
  • __CLASS__ : La classe en cours, similaire à get_class($this) ;
  • __METHOD__ : La méthode en cours ;
  • __NAMESPACE__ : L'espace de noms en cours (depuis les versions 5.3 et 6.0 de PHP).
Exemple :
Sélectionnez
<?php
echo __LINE__; //affiche "2"
echo __LINE__; //affiche "3"
echo __LINE__; //affiche "4"

III-I-3. Fonctions utiles

define() déclare une nouvelle constante :
Sélectionnez
<?php
define('MAX_LIGNES', 3);
defined() permet de savoir si une constante est déjà définie :
Sélectionnez
<?php
if(defined('MAX_LIGNES'))
{
    echo 'Constante définie';
}
else
{
    echo 'Constante non définie';
}
get_defined_constants() retourne toutes les constantes définies :
Sélectionnez
<?php
print_r(get_defined_constants());
contant() retourne la valeur d'une constante :
Sélectionnez
<?php
define('LOGIN', 'Yogui');

echo LOGIN; //ok
echo constant('LOGIN'); //identique à la ligne précédente, sauf qu'on peut aussi bien mettre une variable contenant "LOGIN"

III-I-4. Utilisation

Les constantes sont particulièrment utiles pour les valeurs de configuration. Par exemple, si vous avez besoin d'un nom d'utilisateur et d'un mot de passe pour vous connecter à une base de données, vous devriez utiliser des constantes afin d'éviter qu'une portion de votre script ne modifie ces valeurs par inadvertance (une collision de noms est si vite arrivée...).

 
Sélectionnez
<?php
define('DB_LOGIN', 'Yogui');
define('DB_PASSWORD', 'pass');

Si, dans la suite du script, vous souhaitez utiliser le même nom de constante, PHP vous avertira par une erreur car ce nom existe déjà. Si vous utilisiez une variable, sa valeur serait écrasée sans préavis...

III-J. Tableaux

III-J-1. Syntaxe

Un tableau est une variable contenant plusieurs valeurs. En PHP, les variables étant faiblement typées, les tableaux sont très simples à manipuler.

On accède au tableau entier en utilisant le nom de la variable, ou bien à un élément concret au moyen des crochets [ et ]. Ce qui se situe entre les crochets est appelé "index" ou encore "clef" de l'élément du tableau, et un même index est unique dans un tableau.

Affectation d'un tableau entier :
Sélectionnez
<?php
$nombres = array(3, 6, 9); //ce tableau contient trois valeurs

echo $nombres[1]; //accès direct à l'élément d'index 1, c'est-à-dire le deuxième élément
print_r($nombres); //affichage du tableau complet
Ajout de cases à un tableau vide ou existant :
Sélectionnez
<?php
$nombres = array();
$nombres[] = 3; //ajout à la position suivante = zéro
$nombres[] = 6; //ajout à la position suivante = un
$nombres[] = 9; //ajout à la position suivante = deux

var_dump($nombres[1]); //accès direct à l'élément en position 1
print_r($nombres); //affichage complet
 
Sélectionnez
int(6)
Array
(
    [0] => 3
    [1] => 6
    [2] => 9
)

L'indice permettant d'indexer le tableau peut être numérique ou chaîne. Si on ne spécifie rien (comme ci-dessus), ce sont des valeurs numériques successives. On peut voir ici que le premier élément d'un tableau prend l'index zéro, ce qui est tout à fait habituel dans les langages de programmation.

Affectation d'un tableau entier :
Sélectionnez
<?php
$positions = array(
    0 => 'début',
    1 => 'milieu',
    2 => 'fin'
);

echo $positions[1]; //accès direct à l'élément en position 1
print_r($positions); //affichage complet
Ajout de cases à un tableau vide ou existant :
Sélectionnez
<?php
$positions = array();
$positions[0] = 'début'; //ajout à la position zéro
$positions[1] = 'milieu'; //ajout à la position un
$positions[2] = 'fin'; //ajout à la position deux

var_dump($positions[1]); //accès direct à l'élément en position 1
print_r($positions); //affichage complet
 
Sélectionnez
string(6) "milieu"
Array
(
    [0] => début
    [1] => milieu
    [2] => fin
)

L'index d'un élément permet d'y accéder aussi bien en lecture qu'en modification ou suppression :

Modification d'un élément :
Sélectionnez
<?php
$nombres = array();
$nombres[] = 3; //ajout à la position suivante = zéro
$nombres[] = 6; //ajout à la position suivante = un
$nombres[] = 9; //ajout à la position suivante = deux

print_r($nombres); //affichage complet

$nombres[1] = 12; //modification de l'élément en position 1

print_r($nombres); //affichage complet
 
Sélectionnez
Array
(
    [0] => 3
    [1] => 6
    [2] => 9
)
Array
(
    [0] => 3
    [1] => 12
    [2] => 9
)

Puisque chaque case d'un tableau est une variable à part entière, elle peut être de n'importe quel type (nombre, chaîne, ressource, tableau, objet...), ce qui nous permet d'imbriquer les tableaux si nécessaire.

Lorsqu'un tableau est indexé par des chaînes plutôt que par des nombres, on parle de tableau associatif :

Ajout de cases à un tableau vide ou existant :
Sélectionnez
<?php
$positions = array();
$positions['zéro'] = 'début';
$positions['un'] = 'milieu';
$positions['deux'] = 'fin';

var_dump($positions['un']); //accès direct à l'élément en position (string)"un"
print_r($positions); //affichage complet
 
Sélectionnez
string(6) "milieu"
Array
(
    [zéro] => début
    [un] => milieu
    [deux] => fin
)

Dans le cas d'un tableau associatif, on peut utiliser n'importe quelle chaîne comme index. Il n'y a pas de restriction sur le nom des indexes comme il y en a pour le nom des variables. On peut même utiliser le contenu d'une variable pour indexer un élément d'un tableau :

 
Sélectionnez
<?php
$positions = array();
$positions['zéro'] = 'début';
$positions['un'] = 'milieu';
$positions['deux'] = 'fin';

$index = 'un';
echo $positions[$index]; //affiche "milieu"

Il existe plusieurs manières de parcourir un tableau :

 
Sélectionnez
<?php
$nombres = array(3, 6, 9);
foreach($nombres as $nombre)
{
    echo $nombre.'<br/>';
}
 
Sélectionnez
<?php
$nombres = array(3, 6, 9);
foreach($nombres as $i => $nombre)
{
    echo $i.' '.$nombre.'<br/>';
}
 
Sélectionnez
<?php
$nombres = array(3, 6, 9);
for($i=0; $i<count($nombres); ++$i)
{
    echo $i.' '.$nombres[$i].'<br/>';
}
 
Sélectionnez
<?php
$nombres = array(3, 6, 9);
while(list($i, $nombre) = each($nombres))
{
    echo $i.' '.$nombre.'<br/>';
}

III-J-2. Pointeur interne

Le pointeur interne d'un tableau est une valeur manipulée uniquement par PHP lui-même, en arrière-plan. C'est la position à laquelle PHP s'est arrêté lorsqu'il a utilisé le tableau pour la dernière fois (dans le cas d'un parcours séquentiel).

Nous y reviendrons par la suite, notamment lors des chapitres sur les boucles (structures de contrôle) et sur les interfaces (programmation orientée objet).

Cela permet par exemple d'avoir un tableau indexé par des numéros mais dont l'ordre des éléments ne suit pas ces numéros, ou bien de réorganiser les clefs d'un tableau associatif, etc.

III-J-3. Fonctions utiles

  • count() : Compter le nombre d'éléments d'un tableau ;
  • *sort() : Trier un tableau (nombreuses fonctions disponibles) ;
  • array_*() : cf. la documentation (nombreuses fonctions disponibles) ;
  • list() : Assigne plusieurs valeurs en une opération (habituellement depuis un tableau) ;
  • current() : Retourne l'élément du tableau désigné par son pointeur interne ;
  • reset() : Réinitialise le pointeur interne du tableau ;
  • next() : Avance le pointeur interne puis agit comme current() ;
  • prev() : Recule le pointeur interne puis agit comme current().

III-K. Structures de contrôle

III-K-1. Conditionnelle "if"

Syntaxe :
Sélectionnez
<?php
if(<expression>)
{
    <instructions>
}

La structure conditionnelle if/else est l'une des plus classiques des langages de programmation. Elle permet d'effectuer des opérations ou d'autres opérations selon certaines conditions.

Elle s'écrit avec le mot clef "if" et un paramètre qui peut être une valeur, une variable, une comparaison, bref tout type d'instruction. Si l'instruction est évaluée à TRUE, alors on rentre dans la branche ; sinon, on rentre dans la branche du "else" (qui est facultative).

Le code à exécuter (après la condition entre parenthèses) peut être une simple instruction ou bien un bloc d'instructions délimitées par des accolades. L'une des bonnes pratiques de programmation indique la préférence systématique pour les accolades.

Exemple :
Sélectionnez
<?php
if(2*4 > 5)
{
    echo 'strictement supérieur à 5';
}
else
{
    echo 'inférieur ou égal à 5';
}
Équivalent à (mais il est préférable d'éviter cette écriture) :
Sélectionnez
<?php
if(2*4 > 5) echo 'strictement supérieur à 5';
else echo 'inférieur ou égal à 5';

III-K-2. Alternative "switch"

Syntaxe :
Sélectionnez
<?php
switch(<expression>)
{
    case <valeur 1>:
        <instructions>
    break;

    case <valeur 2>:
        <instructions>
    break;

    ...

    default:
        <instructions>
}

Lorsqu'une variable ou une instruction peut prendre une valeur parmi une liste connue, alors il est préférable d'utiliser le mot clef "switch" plutôt que des "if/else".

Exemple :
Sélectionnez
<?php
switch($variable)
{
    case 1:
        echo 'Choix numéro un';
    break;

    case 2:
        echo 'Choix numéro deux';
    break;

    case 3:
        echo 'Choix numéro trois';
    break;

    default:
        echo 'Choix invalide';
}
Équivalent à (mais il est préférable d'éviter cette écriture) :
Sélectionnez
<?php
if($variable == 1)
{
    echo 'Choix numéro un';
}
else
{
    if($variable == 2)
    {
        echo 'Choix numéro deux';
    }
    else
    {
        if($variable == 3)
        {
            echo 'Choix numéro trois';
        }
        else
        {
            echo 'Choix invalide';
        }
    }
}

Le nombre de case peut varier suivant l'utilisation, cela dépend de la situation. Le mot clef "break" oblige PHP à sortir du bloc switch.

Certains langages ont des restrictions sur le case, qui ne rendent le mot clef switch utilisable qu'avec des valeurs entières. PHP étant un langage à typage faible, cette restriction ne s'applique pas et chaque case peut contenir une chaîne voire même une instruction complète.

Le mot clef break est facultatif : s'il n'est pas précisé, le case suivant est évalué à TRUE jusqu'à rencontrer la fin du switch ou bien un break. Ici par exemple, le même traitement est appliqué à "BrYs", "mathieu" et "Yogui" :

 
Sélectionnez
<?php
switch($membre)
{
    case 'Marc Lussac':
        echo 'Bonjour ô grand manitou';
    break;

    case 'BrYs':
    case 'mathieu':
    case 'Yogui':
        echo 'Bonjour '.$membre;
    break;

    default:
        echo 'Utilisateur invalide';
}

Le mot clef default est facultatif, mais toujours le mettre fait partie des bonnes pratiques. Il est le cas par défaut, c'est-à-dire si aucun autre cas n'a été validé. Dans l'exemple ci-dessus, default n'est exécuté que si $membre ne vaut aucun des quatre noms mentionnés.

L'instruction switch est parfois subtile, mais souvent très intéressante. Sa maîtrise vient avec la pratique, il faut donc faire des exercices en situation réelle.

 
Sélectionnez
<?php
$i = 4; //modifier pour tester l'effet
switch($i)
{
    case 1:
        echo 'un';
    break;

    case 2:
        echo 'deux';
    break;

    default: //valide si $i ne vaut ni 1, ni 2, ni 3
        echo $i;
    break;

    case 3:
        echo 'trois';
    break;
}

Ici, le bon sens nous souffle que le cas default est mal situé : il devrait être en dernière position car c'est le dernier recours.

III-K-3. Boucle "for"

Syntaxe :
Sélectionnez
<?php
for(<initialisation> ; <continuer tant que> ; <incrémentation>)
{
    <instructions>
}

La boucle "for" permet d'effectuer un groupe d'instructions un nombre déterminé de fois. Elle comprend trois paramètres qui sont habituellement des instructions :

Exemples :
Sélectionnez
<?php
//afficher tous les chiffres de 0 à 9
for($i=0; $i<10; ++$i)
{
    echo $i;
}

//afficher toutes les lettres de l'alphabet français
for($lettre='a'; $lettre<='z', ++$lettre)
{
    echo $lettre;
}
Voici comment cela se passe dans le 1° exemple :
  1. $i est initialisé à "0" ;
  2. PHP vérifie si l'instruction "$i<10" est TRUE ;
  3. Si c'est TRUE on continue, sinon la boucle est terminée ;
  4. PHP exécute le corps de la boucle ;
  5. PHP exécute l'instruction d'incrémentation : "++$i" ;
  6. Retour au 2° point.

La boucle "for" est à utiliser exclusivement lorsque l'on connaît d'avance le nombre de tours de boucle à effectuer.

Le deuxième paramètre (aka "continuer tant que", qui vaut ici "$i<10") est évalué à chaque tour de boucle. Il est donc préférable que ce soit une valeur fixe afin d'économiser le temps processeur et sous peine de nous exposer à des "boucles infinies".

Exemple de perte de performances :
Sélectionnez
<?php
$users = array('BrYs', 'mathieu', 'Yogui');

//perte de performances puisque count() est recalculé à chaque itération :
for($i=0; $i<count($users); ++$i)
{
    echo $i.' '.$users[$i].'<br/>';
}

//ok :
$nb_users = count($users);
for($i=0; $i<$nb_users; ++$i)
{
    echo $i.' '.$users[$i].'<br/>';
}
Exemples de boucles infinies (à éviter) :
Sélectionnez
<?php
for(;;) //aucune condition de fin de boucle
{
    //...
}

for($i=0; $i=-1; ++$i) //$i n'atteindra jamais -1
{
    //...
}

III-K-4. Boucle "while"

Syntaxe :
Sélectionnez
<?php
while(<continuer tant que>)
{
    <instructions>
}

Une boucle "while" est prévue pour effectuer un groupe d'instructions un nombre indéfini de fois. La condition de fin de boucle dépend souvent du résultat d'une comparaison de valeurs. Un exemple typique d'utilisation est la lecture d'un flux, par exemple un fichier :

 
Sélectionnez
<?php
$file = fopen('file.ext', 'r'); //ouverture d'un fichier en lecture
while(!feof($file)) //tant que ce n'est pas la fin du fichier (End Of File)
{
    echo fread($file, 8192); //lecture d'une ligne
}
fclose($file); //fermeture du descripteur de fichier
Voici comment cela se passe dans l'exemple :
  1. $file est initialisé à l'état du fichier (EOF si le fichier est vide, une valeur non nulle sinon) ;
  2. PHP vérifie la condition, donc ici si nous ne sommes pas à la fin du fichier ;
  3. Si c'est TRUE on continue, sinon la boucle est terminée ;
  4. PHP exécute le corps de la boucle ;
  5. Retour au 2° point.

Une autre utilisation classique de la boucle "while" est de mettre une ligne d'affectation comme condition :

 
Sélectionnez
//exécution d'une requête définie plus haut dans le script
$db_result = mysql_query($sql);
while($row = mysql_fetch_assoc($db_result)) //tant qu'il y a un résultat
{
    print_r($row);
}

Dans ce cas, la condition du while est la valeur de l'expression "$line = fread($file, 8192)", c'est-à-dire le résultat de l'opération, soit la valeur de $line après affectation. Cela peut s'exprimer par la question "est-ce que l'affectation a pu se faire ?".

La boucle "while" est à utiliser exclusivement lorsque l'on ne connaît pas d'avance le nombre de tours de boucle à effectuer. Cela restreint beaucoup ses cas d'utilisation, car PHP dispose de très nombreux moyens de compter le nombre d'éléments d'un tableau, de lire des fichiers, etc. sans obliger à l'utilisation de "while".

Exemple de boucle infinie :
Sélectionnez
<?php
while(TRUE)
{
    //...
}

III-K-5. Boucle "do while"

Syntaxe :
Sélectionnez
<?php
do
{
    <instructions>
} while(<continuer tant que>);

Cette boucle fonctionne sur un principe similaire au "while", mais le premier tour de boucle est effectué avant toute chose.

Dans d'autres langages, une boucle "do...while" est utilisée par exemple pour afficher un menu à l'écran et attendre la réponse de l'utilisateur : on sait d'avance que le menu est affiché au moins une fois, mais on ne sait pas d'avance quand l'utilisateur souhaitera quitter l'application. Cet exemple est malheureusement inefficace en PHP, puisqu'un script se termine sans que l'utilisateur puisse interagir.

 
Sélectionnez
<?php
do
{
    menu_display(); //définir cette fonction selon le besoin
    $choice = get_user_choice(); //définir cette fonction selon le besoin
    switch($choice)
    {
        //instructions selon la valeur de $choice
    }
} while($choice != CHOICE_LEAVE); //définir cette constante selon le besoin

III-K-6. Boucle "each"

Cette instruction n'est pas vraiment une boucle mais on l'utilise généralement conjointement à un type de boucle. Elle est prévue spécialement pour parcourir les tableaux :

 
Sélectionnez
<?php
$membres = array('BrYs', 'mathieu', 'Yogui');
print_r(each($membres));
print_r(each($membres));
print_r(each($membres));

Chaque utilisation de la fonction fait avancer le pointeur interne du tableau, c'est-à-dire la position à laquelle PHP s'est arrêté la dernière fois qu'il a consulté le tableau.

Afin de simplifier son utilisation, on la couple souvent avec une boucle "while" :

 
Sélectionnez
<?php
$membres = array('BrYs', 'mathieu', 'Yogui');
while(list($i, $membre) = each($membres))
{
    echo $membre;
}

À mon avis, cette utilisation n'est pas optimale à cause de la sémantique du langage. L'exécution est rapide, mais le code n'est pas très clair. Le construct foreach est souvent plus intéressant de ce point de vue.

III-K-7. Boucle "foreach"

 
Sélectionnez
<?php
foreach(<tableau> as <element>)
{
    <instructions>
}
 
Sélectionnez
<?php
foreach(<tableau> as <clef> => <element>)
{
    <instructions>
}

Le mot clef "each" étant assez complexe à utiliser, PHP propose une boucle très pratique : foreach.

 
Sélectionnez
<?php
$membres = array('BrYs', 'mathieu', 'Yogui');

//parcours du tableau :
foreach($membres as $membre)
{
    echo $membre; //affiche tour à tour "BrYs" puis "mathieu" puis "Yogui"
}

//parcours avec clefs :
foreach($membres as $i => $membre)
{
    //affiche tour à tour "0 BrYs" puis "1 mathieu" puis "2 Yogui"
    echo $i . ' ' . $membre;
}

//alternative :
foreach($membres as $i => $membre)
{
    //affiche tour à tour "0 BrYs" puis "1 mathieu" puis "2 Yogui"
    echo $i . ' ' . $membres[$i];
}

III-L. Fonctions

III-L-1. Syntaxe

Syntaxe :
Sélectionnez
<?php
function <nom de la fonction> (<noms des paramètres>)
{
    <instructions>
    return <valeur>; (optionnel)
}

Une fonction permet de réutiliser facilement du code PHP. Par exemple si vous devez effectuer la même suite d'opérations à plusieurs endroits de votre code, il est sans doute judicieux de la mettre dans une fonction. Cela vous permet de ne pas dupliquer le code source et d'en faciliter la maintenance.

Une fonction se déclare en utilisant le mot clef "function" suivi du nom de la fonction (mêmes règles que pour les noms de variables), d'un couple de parenthèses et d'un couple d'accolades. Les parenthèses contiennent la liste des paramètres (de zéro à l'infini) et les accolades contiennent les actions de la fonction.

En PHP, le terme "procédure" est très peu utilisé car on part du principe que toutes les fonctions devraient retourner une valeur : au minimum, si la fonction a réussi ou non (booléen). Toutefois, il ne s'agit ici que d'une convention : d'un point de vue syntaxique, il est possible d'avoir une fonction qui n'utilise pas le mot clef "return" (mais ce serait probablement une mauvaise idée).

La valeur de retour d'une fonction est définie par le mot clef "return". Dès que ce mot clef est exécuté, PHP sort de la fonction.

Exemple :
Sélectionnez
<?php
function ma_fonction()
{
    echo 'essai 1';
    return TRUE; //PHP sort de la fonction en renvoyant la valeur "vrai"
    echo 'essai 2'; //cette instruction ne sera jamais exécutée
}

Voyons un exemple d'application :

Code répétitif :
Sélectionnez
<?php
var_dump(3 * 100 / 8);
var_dump(2 * 100 / 72);
var_dump(5 * 100 / 50);
Code mis en facteur :
Sélectionnez
<?php
function pourcent($x, $y)
{
    return $x * 100 / $y;
}

var_dump(pourcent(3, 8));
var_dump(pourcent(2, 72));
var_dump(pourcent(5, 50));
 
Sélectionnez
float(37.5)
float(2.7777777777778)
int(10)

La logique de calcul est ici centralisée dans la fonction pourcent(), ce qui facilite la maintenance. On peut par exemple utiliser des fonctions pour la gestion des grands nombres, sans devoir retoucher le code de toute l'application :

Code répétitif modifié (à titre indicatif) :
Sélectionnez
<?php
var_dump(bcdiv(bcmul(3, 100), 8, 2));
var_dump(bcdiv(bcmul(2, 100), 72, 2));
var_dump(bcdiv(bcmul(5, 100), 50, 2));
Code mis en facteur modifié :
Sélectionnez
<?php
function pourcent($x, $y)
{
    return bcdiv(bcmul($x, 100), $y, 2);
}

var_dump(pourcent(3, 8));
var_dump(pourcent(2, 72));
var_dump(pourcent(5, 50));
 
Sélectionnez
string(5) "37.50"
string(4) "2.77"
string(5) "10.00"

Notez que seul le corps de la fonction a été modifié dans le code mis en facteur, mais que tout le programme est affecté.

Il ne faut pas faire des fonctions à tort et à travers, il est par exemple préférable que la fonction retourne une valeur simple plutôt qu'une valeur complexe, et il vaut mieux éviter d'inclure du code HTML dans le retour d'une fonction.

III-L-2. Visibilité des variables

La visibilité (ou "scope") d'une variable dépend de sa première utilisation. Une variable n'est visible que dans la fonction dans laquelle elle a été définie :

 
Sélectionnez
<?php
$x = 5;
echo $x; //affiche "5"
test(); //affiche une erreur
echo $x; //affiche "5"


function test()
{
    echo $x; //illégal car $x n'est pas défini dans la fonction test()
}
 
Sélectionnez
<?php
$x = 5;
echo $x; //affiche "5"
test();
echo $x; //affiche "5" car ce $x-ci n'est plus celui de la fonction test()


function test()
{
    $x = 7;
    echo $x; //affiche "7" car $x appartient à la fonction test()
}
 
Sélectionnez
<?php
$x = 5;
echo $x; //affiche "5"
$objet_test = new Test(7);
echo $objet_test->x; //affiche "7"


class Test
{
    public $x;
    public function __construct($valeur)
    {
        $this->x = $valeur;
    }
}

Il existe cependant un mot clef "global" permettant d'outrepasser cette restriction :

 
Sélectionnez
<?php<?php
$x = 5;
echo $x; //affiche "5"
test(); //affiche "5"
echo $x; //affiche "5"


function test()
{
    global $x;
    echo $x; //reprend le "$x" du scope global
}
 
Sélectionnez
<?php
$x = 5;
echo $x; //affiche "5"
test(); //affiche "7"
echo $x; //affiche "7"


function test()
{
    global $x;
    $x = 7;
    echo $x; //modifie "$x" dans le scope global
}

III-L-3. Fonctions et constantes utiles

Fonctions :
  • function_exists() : Est-ce que la fonction existe ?
  • get_defined_functions() : Liste des fonctions définies ;
  • func_num_args() : Nombre de paramètres transmis à la fonction courante ;
  • func_get_arg() : Un paramètre de la fonction courante ;
  • func_get_args() : Tous les paramètres de la fonction courante ;
  • create_function() : Créer une fonction utilisateur à partir du code PHP fourni en commentaires.

L'utilisation de create_function() doit se faire uniquement après mûre réflexion (question de sécurité)...

Constantes magiques :
  • __FUNCTION__ : Donne le nom de la fonction en cours.

précédentsommairesuivant

Copyright © 2008 Guillaume Rossolini. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.