Skip to content

3. Les bases de PHP

3.1. Un premier exemple

Ci-dessous, on trouvera un programme présentant les premières caractéristiques de PHP.

3.1.1. Le programme (exemple_01)


<?php

// ceci est un commentaire
// variable utilisée sans avoir été déclarée
$nom = "dupont";

// un affichage écran
print "nom=$nom\n";

// un tableau avec des éléments de type différent
$tableau = array("un", "deux", 3, 4);

// son nombre d'éléments
$n = count($tableau);

// une boucle
for ($i = 0; $i < $n; $i++)
  print "tableau[$i]=$tableau[$i]\n";

// initialisation de 2 variables avec le contenu d'un tableau
list($chaine1, $chaine2) = array("chaine1", "chaine2");

// concaténation des 2 chaînes
$chaine3 = $chaine1 . $chaine2;

// affichage résultat
print "[$chaine1,$chaine2,$chaine3]\n";

// utilisation fonction
affiche($chaine1);

// le type d'une variable peut être connu
afficheType($n);
afficheType($chaine1);
afficheType($tableau);

// le type d'une variable peut changer en cours d'exécution
$n = "a changé";
afficheType($n);

// une fonction peut rendre un résultat
$res1 = f1(4);
print "res1=$res1\n";

// une fonction peut rendre un tableau de valeurs
list($res1, $res2, $res3) = f2();
print "(res1,res2,res3)=[$res1,$res2,$res3]\n";

// on aurait pu récupérer ces valeurs dans un tableau
$t = f2();
for ($i = 0; $i < count($t); $i++)
  print "t[$i]=$t[$i]\n";

// des tests
for ($i = 0; $i < count($t); $i++)
// n'affiche que les chaînes
  if (getType($t[$i]) == "string")
    print "t[$i]=$t[$i]\n";

// d'autres tests
for ($i = 0; $i < count($t); $i++){
// n'affiche que les entiers >10
  if (getType($t[$i]) == "integer" and $t[$i] > 10)
    print "t[$i]=$t[$i]\n";
}

// une boucle while
$t = array(8, 5, 0, -2, 3, 4);
$i = 0;
$somme = 0;
while ($i < count($t) and $t[$i] > 0) {
  print "t[$i]=$t[$i]\n";
  $somme+=$t[$i];   //$somme=$somme+$t[$i]
  $i++;             //$i=$i+1
}
print "somme=$somme\n";

// fin programme
exit;

//----------------------------------
function affiche($chaine) {
  // affiche $chaine
  print "chaine=$chaine\n";
}

//----------------------------------
function afficheType($variable) {
  // affiche le type de $variable
  print "type[$variable]=" . getType($variable) . "\n";
}

//----------------------------------
function f1($param) {
  // ajoute 10 à $param
  return $param + 10;
}

//----------------------------------
function f2() {
  // rend 3 valeurs
  return array("un", 0, 100);
}
?>

Les résultats :

nom=dupont
tableau[0]=un
tableau[1]=deux
tableau[2]=3
tableau[3]=4
[chaine1,chaine2,chaine1chaine2]
chaine=chaine1
type[4]=integer
type[chaine1]=string
type[Array]=array
type[a changé]=string
res1=14
(res1,res2,res3)=[un,0,100]
t[0]=un
t[1]=0
t[2]=100
t[0]=un
t[2]=100
t[0]=8
t[1]=5
somme=13

Commentaires

  • ligne 5 : en PHP, on ne déclare pas le type ds variables. Celles-ci ont un type dynamique qui peut varier au cours du temps
  • $nom représente la variable d'identifiant nom
  • ligne 8 : pour écrire à l'écran, on peut utiliser l'instruction print ou l'instruction echo
  • ligne 11 : le mot clé array permet de définir un tableau. La variable $nom[$i] représente l'élément $i du tableau $tableau.
  • ligne 14 : la fonction count($tableau) rend le nombre d'éléments du tableau $tableau
  • ligne 18 : les chaînes de caractères sont entourées de guillemets " ou d'apostrophes '. A l'intérieur de guillemets, les variables $variable sont évaluées mais pas à l'intérieur d'apostrophes.
  • ligne 21 : la fonction list permet de rassembler des variables dans une liste et de leur attribuer une valeur avec une unique opération d'affectation. Ici $chaine1="chaine1" et $chaine2="chaine2".
  • ligne 24 : l'opérateur . est l'opérateur de concaténation de chaînes.
  • ligne 88 : le mot clé function définit une fonction. Une fonction rend ou non des valeurs par l'instruction return. Le code appelant peut ignorer ou récupérer les résultats d'une fonction. Une fonction peut être définie n'importe où dans le code.
  • ligne 90 : la fonction prédéfinie getType($variable) rend une chaîne de caractères représentant le type de $variable. Ce type peut changer au cours du temps.
  • ligne 79 : la fonction prédéfinie exit arrête le script.

3.2. La portée des variables

3.2.1. Programme 1 (exemple_02)


<?php

// portée des variables

function f1() {
  // on utilise la variable globale $i
  $i = &$GLOBALS["i"];
  $i++;
  $j = 10;
  print "f1[i,j]=[$i,$j]\n";
}

function f2() {
  // on utilise la variable globale $i
  $i = &$GLOBALS["i"];
  $i++;
  $j = 20;
  print "f2[i,j]=[$i,$j]\n";
}

function f3() {
  // on utilise une variable locale $i
  $i = 4;
  $j = 30;
  print "f3[i,j]=[$i,$j]\n";
}

// tests
$i = 0;
$j = 0;  // ces deux variables sont connues d'une fonction f via le tableau $GLOBALS
f1();
f2();
f3();
print "test[i,j]=[$i,$j]\n";
?>

Les résultats :

1
2
3
4
f1[i,j]=[1,10]
f2[i,j]=[2,20]
f3[i,j]=[4,30]
test[i,j]=[2,0]

Commentaires

  • lignes 29-30 : définissent 2 variables $i et $j du programme principal. Ces variables ne sont pas connues à l'intérieur des fonctions. Ainsi, ligne 9, la variable $j de la fonction f1 est une variable locale à la fonction f1 et est différente de la variable $j du programme principal. Une fonction peut accéder à une variable $variable du programme principal via un tableau de variables globales appelé $GLOBALS. Ligne 7, la notation $GLOBALS["i"] désigne la variable globale $i du programme principal. Si nous écrivons
$i=$GLOBALS["i"]

une variable $i locale se voit affecter la valeur de la variable $i globale. On a là deux variables différentes et modifier la variable locale $i ne modifiera pas la variable globale $i. La notation

$i=&Globals["i"]

fait que la variable locale $i a la même adresse mémoire que la variable globale $i. Manipuler la variable locale $i revient alors à manipuler la variable globale $i.

3.2.2. Programme 2 (exemple_03)


<?php

// la portée d'une variable est globale aux blocs de code
$i = 0; {
  $i = 4;
  $i++;
}
print "i=$i\n";
?>

Les résultats :

i=5

Commentaires

Dans certains langages, une variable définie à l'intérieur d'accolades a la portée de celles-ci : elle n'est pas connue à l'extérieur de celles-ci. Les résultats ci-dessus montrent qu'il n'en est rien en PHP. La variable $i définie ligne 5 à l'intérieur des accolades est la même que celle utilisée lignes 4 et 8 à l'extérieur de celles-ci.

3.3. Les tableaux

3.3.1. Tableaux classiques à une dimension (exemple_04)


<?php

// tableaux classiques
// initialisation
$tab1 = array(0, 1, 2, 3, 4, 5);

// parcours - 1
print "tab1 a " . count($tab1) . " éléments\n";
for ($i = 0; $i < count($tab1); $i++)
  print "tab1[$i]=$tab1[$i]\n";

// parcours - 2
print "tab1 a " . count($tab1) . " éléments\n";
reset($tab1);
while (list($clé, $valeur) = each($tab1))
  print "tab1[$clé]=$valeur\n";

// ajout d'éléments
$tab1[] = $i++;
$tab1[] = $i++;

// parcours - 3
print "tab1 a " . count($tab1) . " éléments\n";
$i = 0;
foreach ($tab1 as $élément) {
  print "tab1[$i]=$élément\n";
  $i++;
}

// suppression dernier élément
array_pop($tab1);

// parcours - 4
print "tab1 a " . count($tab1) . " éléments\n";
for ($i = 0; $i < count($tab1); $i++)
  print "tab1[$i]=$tab1[$i]\n";

// suppression premier élément
array_shift($tab1);

// parcours - 5
print "tab1 a " . count($tab1) . " éléments\n";
for ($i = 0; $i < count($tab1); $i++)
  print "tab1[$i]=$tab1[$i]\n";

// ajout en fin de tableau
array_push($tab1, -2);

// parcours - 6
print "tab1 a " . count($tab1) . " éléments\n";
for ($i = 0; $i < count($tab1); $i++)
  print "tab1[$i]=$tab1[$i]\n";

// ajout en début de tableau
array_unshift($tab1, -1);

// parcours - 7
print "tab1 a " . count($tab1) . " éléments\n";
for ($i = 0; $i < count($tab1); $i++)
  print "tab1[$i]=$tab1[$i]\n";
?>

Les résultats :

tab1 a 6 éléments
tab1[0]=0
tab1[1]=1
tab1[2]=2
tab1[3]=3
tab1[4]=4
tab1[5]=5
tab1 a 6 éléments
tab1[0]=0
tab1[1]=1
tab1[2]=2
tab1[3]=3
tab1[4]=4
tab1[5]=5
tab1 a 8 éléments
tab1[0]=0
tab1[1]=1
tab1[2]=2
tab1[3]=3
tab1[4]=4
tab1[5]=5
tab1[6]=6
tab1[7]=7
tab1 a 7 éléments
tab1[0]=0
tab1[1]=1
tab1[2]=2
tab1[3]=3
tab1[4]=4
tab1[5]=5
tab1[6]=6
tab1 a 6 éléments
tab1[0]=1
tab1[1]=2
tab1[2]=3
tab1[3]=4
tab1[4]=5
tab1[5]=6
tab1 a 7 éléments
tab1[0]=1
tab1[1]=2
tab1[2]=3
tab1[3]=4
tab1[4]=5
tab1[5]=6
tab1[6]=-2
tab1 a 8 éléments
tab1[0]=-1
tab1[1]=1
tab1[2]=2
tab1[3]=3
tab1[4]=4
tab1[5]=5
tab1[6]=6
tab1[7]=-2

Commentaires

Le programme ci-dessus montre des opérations de manipulation d'un tableau de valeurs. Il existe deux notations pour les tableaux en PHP :

$tableau=array("un",2,"trois")
$contraires=array("petit"=>"grand", "beau"=>"laid", "cher"=>"bon marché")

Le tableau 1 est appelé tableau et le tableau 2 un dictionnaire où les éléments sont notés clé => valeur. La notation $contraires["beau"] désigne la valeur associée à la clé "beau". C'est donc ici la chaîne "laid". Le tableau 1 n'est qu'une variante du dictionnaire et pourrait être noté :

$tableau=array(0=>"un",1=>2,2=>"trois")

On a ainsi $tableau[2]="trois". Au final, il n'y a que des dictionnaires. Dans le cas d'un tableau classique de n éléments, les clés sont les nombres entiers de l'intervalle [0,n-1].

  • ligne 15 : la fonction each($tableau) permet de parcourir un dictionnaire. A chaque appel, elle rend une paire (clé,valeur) de celui-ci.
  • ligne 14 : la fonction reset($dictionnaire) positionne la fonction each sur la première paire (clé,valeur) du dictionnaire.
  • ligne 15 : la boucle while s'arrête lorsque la fonction each rend une paire vide à la fin du dictionnaire.
  • ligne 19 : la notation $tableau[]=valeur ajoute l'élément valeur comme dernier élément de $tableau.
  • ligne 25 : le tableau est parcouru avec un foreach. Cet élément syntaxique permet de parcourir un dictionnaire, donc un tableau, selon deux syntaxes :
foreach($dictionnaire as $clé=>$valeur)
foreach($tableau as $valeur)

La première syntaxe ramène une paire (clé,valeur) à chaque itération alors que la seconde syntaxe ne ramène que l'élément valeur du dictionnaire.

  • ligne 31 : la fonction array_pop($tableau) supprime le dernier élément de $tableau
  • ligne 39 : la fonction array_shift($tableau) supprime le premier élément de $tableau
  • ligne 47 : la fonction array_push($tableau,valeur) ajoute valeur comme dernier élément de $tableau
  • ligne 39 : la fonction array_unshift($tableau,valeur) ajoute valeur comme premier élément de $tableau

3.3.2. Le dictionnaire (exemple_05)


<?php

// dictionnaires
$conjoints = array("Pierre" => "Gisèle", "Paul" => "Virginie", "Jacques" => "Lucette", "Jean" => "");

// parcours - 1
print "Nombre d'éléments du dictionnaire : " . count($conjoints) . "\n";
reset($conjoints);
while (list($clé, $valeur) = each($conjoints))
  print "conjoints[$clé]=$valeur\n";

// tri du dictionnaire sur la clé
ksort($conjoints);

// parcours - 2
reset($conjoints);
while (list($clé, $valeur) = each($conjoints))
  print "conjoints[$clé]=$valeur\n";

// liste des clés du dictionaire
$clés = array_keys($conjoints);
for ($i = 0; $i < count($clés); $i++)
  print "clés[$i]=$clés[$i]\n";

// liste des valeurs du dictionnaire
$valeurs = array_values($conjoints);
for ($i = 0; $i < count($valeurs); $i++)
  print "valeurs[$i]=$valeurs[$i]\n";

// recherche d'une clé
existe($conjoints, "Jacques");
existe($conjoints, "Lucette");
existe($conjoints, "Jean");

// suppression d'une clé-valeur
unset($conjoints["Jean"]);
print "Nombre d'éléments du dictionnaire : " . count($conjoints) . "\n";
foreach ($conjoints as $clé => $valeur) {
  print "conjoints[$clé]=$valeur\n";
}

// fin
exit;

function existe($conjoints, $mari) {
  // vérifie si la clé $mari existe dans le dictionnaire $conjoints
  if (isset($conjoints[$mari]))
    print "La clé [$mari] existe associée à la valeur [$conjoints[$mari]]\n";
  else
    print "La clé [$mari] n'existe pas\n";
}

?>

Les résultats :

Nombre d'éléments du dictionnaire : 4
conjoints[Pierre]=Gisèle
conjoints[Paul]=Virginie
conjoints[Jacques]=Lucette
conjoints[Jean]=
conjoints[Jacques]=Lucette
conjoints[Jean]=
conjoints[Paul]=Virginie
conjoints[Pierre]=Gisèle
clés[0]=Jacques
clés[1]=Jean
clés[2]=Paul
clés[3]=Pierre
valeurs[0]=Lucette
valeurs[1]=
valeurs[2]=Virginie
valeurs[3]=Gisèle
La clé [Jacques] existe associée à la valeur [Lucette]
La clé [Lucette] n'existe pas
La clé [Jean] existe associée à la valeur []
Nombre d'éléments du dictionnaire : 3
conjoints[Jacques]=Lucette
conjoints[Paul]=Virginie
conjoints[Pierre]=Gisèle

Commentaires

Le code précédent applique à un dictionnaire ce qui a été vu auparavant pour un simple tableau. Nous ne commentons que les nouveautés :

  • ligne 13 : la fonction ksort (key sort) permet de trier un dictionnaire dans l'ordre naturel de la clé.
  • ligne 21 : la fonction array_keys($dictionnaire) rend la liste des clés du dictionnaire sous forme de tableau
  • ligne 26 : la fonction array_values($dictionnaire) rend la liste des valeurs du dictionnaire sous forme de tableau
  • ligne 47 : la fonction isset($variable) rend true si la variable $variable a été définie, false sinon.
  • ligne 36 : la fonction unset($variable) supprime la variable $variable.

3.3.3. Les tableaux à plusieurs dimensions (exemple_06)


<?php

// tableaux classiques multidimensionnels
// initialisation
$multi = array(array(0, 1, 2), array(10, 11, 12, 13), array(20, 21, 22, 23, 24));
// parcours
for ($i1 = 0; $i1 < count($multi); $i1++)
  for ($i2 = 0; $i2 < count($multi[$i1]); $i2++)
    print "multi[$i1][$i2]=" . $multi[$i1][$i2] . "\n";
// dictionnaires multidimensionnels
// initialisation
$multi = array("zéro" => array(0, 1, 2), "un" => array(10, 11, 12, 13), "deux" => array(20, 21, 22, 23, 24));
// parcours
foreach ($multi as $clé => $valeur)
  for ($i2 = 0; $i2 < count($valeur); $i2++)
    print "multi[$clé][$i2]=" . $multi[$clé][$i2] . "\n";
?>

Résultats :

multi[0][0]=0
multi[0][1]=1
multi[0][2]=2
multi[1][0]=10
multi[1][1]=11
multi[1][2]=12
multi[1][3]=13
multi[2][0]=20
multi[2][1]=21
multi[2][2]=22
multi[2][3]=23
multi[2][4]=24
multi[zéro][0]=0
multi[zéro][1]=1
multi[zéro][2]=2
multi[un][0]=10
multi[un][1]=11
multi[un][2]=12
multi[un][3]=13
multi[deux][0]=20
multi[deux][1]=21
multi[deux][2]=22
multi[deux][3]=23
multi[deux][4]=24

Commentaires

  • ligne 5 : les éléments du tableau $multi sont eux-mêmes des tableaux
  • ligne 12 : le tableau $multi devient un dictionnaire (clé,valeur) où chaque valeur est un tableau

3.3.4. Liens entre chaînes et tableaux (exemple_07)


<?php

// chaîne vers tableau
$chaine = "1:2:3:4";
$tab = explode(":", $chaine);

// parcours tableau
print "tab a " . count($tab) . " éléments\n";
for ($i = 0; $i < count($tab); $i++)
  print "tab[$i]=$tab[$i]\n";

// tableau vers chaîne
$chaine2 = implode(":", $tab);
print "chaine2=$chaine2\n";

// ajoutons un champ vide
$chaine.=":";
print "chaîne=$chaine\n";
$tab = explode(":", $chaine);

// parcours tableau
print "tab a " . count($tab) . " éléments\n";
for ($i = 0; $i < count($tab); $i++)
  print "tab[$i]=$tab[$i]\n"; // on a maintenant 5 éléments, le dernier étant vide
  
// ajoutons de nouveau un champ vide
$chaine.=":";
print "chaîne=$chaine\n";
$tab = explode(":", $chaine);

// parcours tableau
print "tab a " . count($tab) . " éléments\n";
for ($i = 0; $i < count($tab); $i++)
  print "tab[$i]=$tab[$i]\n"; // on a maintenant 6 éléments, les deux derniers étant vides
?>

Résultats :

tab a 4 éléments
tab[0]=1
tab[1]=2
tab[2]=3
tab[3]=4
chaine2=1:2:3:4
chaîne=1:2:3:4:
tab a 5 éléments
tab[0]=1
tab[1]=2
tab[2]=3
tab[3]=4
tab[4]=
chaîne=1:2:3:4::
tab a 6 éléments
tab[0]=1
tab[1]=2
tab[2]=3
tab[3]=4
tab[4]=
tab[5]=

Commentaires

  • ligne 5 : la fonction explode($séparateur,$chaine) permet de récupérer les champs de $chaine séparés par $séparateur. Ainsi explode(":",$chaine) permet de récupérer sous forme de tableau les éléments de $chaine qui sont séparés par la chaîne ":".
  • la foncion implode($séparateur,$tableau) fait l'opération inverse de la fonction explode. Elle rend une chaîne de caractères formée des éléments de $tableau séparés par $séparateur.

3.4. Les chaînes de caractères

3.4.1. Notation (exemple_08)


<?php

// notation des chaînes
$chaine1 = "un";
$chaine2 = 'un';
print "[$chaine1,$chaine2]\n";
?>

Résultats :

[un,un]

3.4.2. Comparaison (exemple_09)


<?php

// tests de comparaisons de chaînes
compare("abcd", "abcd");
compare("", "");
compare("1", "");
exit;

function compare($chaine1, $chaine2) {
  // compare chaine1 et chaine2
  if ($chaine1 == $chaine2)
    print "[$chaine1] est égal à [$chaine2]\n";
  else
    print "[$chaine1] est différent de [$chaine2]\n";
}

?>

Résultats :

1
2
3
[abcd] est égal à [abcd]
[] est égal à []
[1] est différent de []

3.5. Les expressions régulières (exemple_10)


<?php

// expression régulières en PHP
// récupérer les différents champs d'une chaîne

// le modèle : une suite de chiffres entourée de caractères quelconques
// on ne veut récupérer que la suite de chiffres
$modèle = "/(\d+)/";
// on confronte la chaîne au modèle
compare($modèle, "xyz1234abcd");
compare($modèle, "12 34");
compare($modèle, "abcd");

// le modèle : une suite de chiffres entourée de caractères quelconques
// on veut la suite de chiffres ainsi que les champs qui suivent et précèdent
$modèle = "/^(.*?)(\d+)(.*?)$/";
// on confronte la chaîne au modèle
compare($modèle, "xyz1234abcd");
compare($modèle, "12 34");
compare($modèle, "abcd");

// le modèle - une date au format jj/mm/aa
$modèle = "/^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$/";
compare($modèle, "10/05/97");
compare($modèle, "  04/04/01  ");
compare($modèle, "5/1/01");

// le modèle - un nombre décimal
$modèle = "/^\s*([+|-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*/";
compare($modèle, "187.8");
compare($modèle, "-0.6");
compare($modèle, "4");
compare($modèle, ".6");
compare($modèle, "4.");
compare($modèle, " + 4");

// fin
exit;

// --------------------------------------------------------------------------
function compare($modèle, $chaîne) {
  // compare la chaîne $chaîne au modèle $modèle
  // on confronte la chaîne au modèle
  $correspond = preg_match($modèle, $chaîne, $champs);
  // affichage résultats
  print "\nRésultats($modèle,$chaîne)\n";
  if ($correspond) {
    for ($i = 0; $i < count($champs); $i++)
      print "champs[$i]=$champs[$i]\n";
  } else
    print "La chaîne [$chaîne] ne correspond pas au modèle [$modèle]\n";
}
?>

Résultats :

Résultats(/(\d+)/,xyz1234abcd)
champs[0]=1234
champs[1]=1234

Résultats(/(\d+)/,12 34)
champs[0]=12
champs[1]=12

Résultats(/(\d+)/,abcd)
La chaîne [abcd] ne correspond pas au modèle [/(\d+)/]

Résultats(/^(.*?)(\d+)(.*?)$/,xyz1234abcd)
champs[0]=xyz1234abcd
champs[1]=xyz
champs[2]=1234
champs[3]=abcd

Résultats(/^(.*?)(\d+)(.*?)$/,12 34)
champs[0]=12 34
champs[1]=
champs[2]=12
champs[3]= 34

Résultats(/^(.*?)(\d+)(.*?)$/,abcd)
La chaîne [abcd] ne correspond pas au modèle [/^(.*?)(\d+)(.*?)$/]

Résultats(/^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$/,10/05/97)
champs[0]=10/05/97
champs[1]=10
champs[2]=05
champs[3]=97

Résultats(/^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$/,  04/04/01  )
champs[0]=  04/04/01  
champs[1]=04
champs[2]=04
champs[3]=01

Résultats(/^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$/,5/1/01)
La chaîne [5/1/01] ne correspond pas au modèle [/^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$/]

Résultats(/^\s*([+|-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*/,187.8)
champs[0]=187.8
champs[1]=
champs[2]=187.8

Résultats(/^\s*([+|-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*/,-0.6)
champs[0]=-0.6
champs[1]=-
champs[2]=0.6

Résultats(/^\s*([+|-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*/,4)
champs[0]=4
champs[1]=
champs[2]=4

Résultats(/^\s*([+|-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*/,.6)
champs[0]=.6
champs[1]=
champs[2]=.6

Résultats(/^\s*([+|-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*/,4.)
champs[0]=4.
champs[1]=
champs[2]=4.

Résultats(/^\s*([+|-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*/, + 4)
champs[0]= + 4
champs[1]=+
champs[2]=4

Commentaires

  • lignes 3-4 : nous utilisons ici les expression régulières pour récupérer les divers champs d'une chaîne de caractères. Les expressions régulières permetent de dépasser les limites de la fonction implode. Le principe est de comparer une chaîne de caractères à une autre chaîne appelée modèle à l'aide de la fonction preg_match :

$correspond = preg_match($modèle, $chaîne, $champs);

La fonction preg_match rend un booléen si le modèle peut être trouvé dans la chaîne. Si oui, $champs[0] représente la sous-chaîne correspondant au modèle. Par ailleurs, si modèle contient des sous-modèles entre parenthèses, $champs[1] est le morceau de $chaîne correspondant au 1er sous-modèle, $champs[2] est le morceau de $chaîne correspondant au 2ième sous-modèle, etc...

Considérons le 1er exemple. Le modèle est défini ligne 8 : il désigne une suite de un ou plusieurs (+) chiffres (\d) placés n'importe où dans une chaîne. Par ailleurs, le modèle définit un sous-modèle entouré de parenthèses.

  • ligne 10 : le modèle /(\d+)/ (suite d'un ou plusieurs chiffres n'importe où dans la chaîne) est comparé à la chaîne "xyz1234abcd". On voit que la sous-chaîne 1234 correspond au modèle. On aura donc $champs[0] égal à "1234". Par ailleurs, le modèle a des sous-modèles entre parenthèses. On aura $champs[1]="1234".
  • ligne 11 : le modèle /(\d+)/ est comparé à la chaîne "12 34". On voit que les sous-chaînes 12 et 34 correspondent au modèle. La comparaison s'arrête à la première sous-chaîne correspondant au modèle. On aura donc, $champs[0]=12 et $champs[1]=12.
  • ligne 12 : le modèle /(\d+)/ est comparé à la chaîne "abcd". Aucune correspondance n'est trouvée.

Explicitons les modèles utilisés dans la suite du code :


$modèle = "/^(.*?)(\d+)(.*?)$/";

début de chaîne (^), puis 0 ou plusieurs (*) caractères quelconques (.) puis 1 ou plusieurs (+) chiffres, puis de nouveau 0 ou plusieurs (*) caractères quelconques (.). Le modèle (.*) désigne 0 ou plusieurs caractères quelconques. Un tel modèle va correspondre à n'importe quelle chaîne. Ainsi le modèle /^(.*)(\d+)(.*)$/ ne sera-t-il jamais trouvé car le premier sous-modèle (.*) va absorber toute la chaîner. Le modèle (.*?)(\d+) désigne lui 0 ou plusieurs caractères quelconques jusqu'au sous-modèle suivant (?), ici \d+. Donc les chiffres ne sont maintenant plus absorbés par le modèle (.*). Le modèle ci-dessus correspond donc à [début de chaîne (^), une suite de caractères quelconques (.*?), une suite d'un ou plusieurs chiffres (\d+), une suite de caractères quelconques (.*?), la fin de la chaîne ($)].


$modèle = "/^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$/";

correspond à [début de chaîne (^), 2 chiffres (\d\d), le caractère / (\/), 2 chiffres, /, 2 chiffres, une suite de 0 ou plusieurs espaces (\s*), la fin de chaîne ($)]


$modèle = "/^\s*([+|-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*/";

[début de chaîne (^), 0 ou plusieurs espaces (\s*), un signe + ou - [+|-] présent 0 ou 1 fois (?), une suite de 0 ou plusieurs espaces (\s*), 1 ou plusieurs chiffres suivis d'un point décimal suivi de zéro ou plusieurs chiffres (\d+\.\d*) ou (|) un point décimal (\.) suivi d'un ou plusieurs chiffres (\d+) ou (|) un ou plusieurs chiffres (\d+), une suite de 0 ou plusieurs espaces (\s*)].

3.6. Mode de passage des paramètres des fonctions (exemple_11)


<?php

// mode de pasage des paramètres

function f(&$i, $j) {
  // $i sera obtenu par référence
  // $j sera obtenu par valeur
  $i++;
  $j++;
  print "f[i,j]=[$i,$j]\n";
}

// ----------------------------------------tests
$i = 0;
$j = 0;
// $i et $j passés par valeurs
f($i, $j);
print "test[i,j]=[$i,$j]\n";
?>

Résultats :

f[i,j]=[1,1]
test[i,j]=[1,0]

Commentaires

Le code ci-dessus montre les deux modes de passage de paramètres à une fonction. Prenons l'exemple suivant :

1
2
3
4
5
6
7
function f(&$a,$b){

}

// programme principal
$i=10; $j=20;
f($i,$j);
  • ligne 1 : définit les paramètres formels $a et $b de la fonction f. Celle-ci manipule ces deux paramètres formels et rend un résultat.
  • ligne 7 : appel de la fonction f avec deux paramètres effectifs $i et $j. Les liens entre les paramètres formels ($a,$b) et les paramètres effectifs ($i,$j) sont définis par la ligne 7
  • &$a : le signe & indique que le paramètre formel $a prendra pour valeur l'adresse du paramètre effectif $i. Dit autrement, $a et $i sont deux références sur un même emplacement mémoire. Manipuler le paramètre formel $a revient à manipuler le paramètre effectif $i. C'est ce que montre l'exécution du code. Ce mode de passage convient aux paramètres de sortie et aux données volumineuses telles que les tableaux et dictionnaires. On appelle ce mode passage, passage par référence.
  • $b : le paramètre formel $b prendra pour valeur celle du paramètre effectif $j. C'est un passage par valeur. Les paramètres formels et effectifs sont deux variables différentes. Manipuler le paramètre formel $b n'a aucune incidence sur le paramètre effectif $j. C'est ce que montre l'exécution du code. Ce mode de passage convient aux paramètres d'entrée.
  • Soit la fonction échange qui admet deux paramètres formels $a et $b. La fonction échange la valeur de ces deux paramètres. Ainsi lors d'un appel échange ($i,$j), le code appelant s'attend à ce que les valeurs des deux paramètres effectifs soient échangés. Ce sont donc des paramètres de sortie (ils sont modifiés). On écrira donc :
function échange(&$a,&$b){....}

3.7. Résultats rendus par une fonction (exemple_12)


<?php

// résultats rendus par une fonction
// une fonction peut rendre plusieurs valeurs dans un tableau
list($res1, $res2, $res3) = f1(10);
print "[$res1,$res2,$res3]\n";
$res = f1(10);
for ($i = 0; $i < count($res); $i++)
  print "res[$i]=$res[$i]\n";

// une fonction peut rendre un pseudo-objet
$res = f2(10);
print "[$res->res1,$res->res2,$res->res3]\n";

// fin
exit;

// fonction f1
function f1($valeur) {
  // rend un tableau ($valeur+1,$aleur+2,$baleur+3)
  return array($valeur + 1, $valeur + 2, $valeur + 3);
}

// fonction f2
function f2($valeur) {
  // rend un pseudo-objet ($valeur+1,$aleur+2,$baleur+3)
  $res->res1 = $valeur + 1;
  ;
  $res->res2 = $valeur + 2;
  $res->res3 = $valeur + 3;
  // rend l'objet
  return $res;
}

?>

Résultats

1
2
3
4
5
[11,12,13]
res[0]=11
res[1]=12
res[2]=13
[11,12,13]

Commentaires

  • le programme précédent montre qu'une fonction PHP peut rendre un ensemble de résultats et non un seul, sous la forme d'un tableau ou d'un objet. La notion d'objet est explicitée un peu plus loin
  • lignes 19-22 : la fonction f1 rend plusieurs valeurs sous la forme d'un tableau
  • lignes 25-33 : la fonction f2 rend plusieurs valeurs sous la forme d'un objet

3.8. Les fichiers texte (exemple_13)


<?php

// exploitation séquentielle d'un fichier texte
// celui-ci est un ensemble de lignes de la forme login:pwd:uid:gid:infos:dir:shell
// chaque ligne est mis dans un dictionnaire sous la forme login => uid:gid:infos:dir:shell

// on fixe le nom du fichier
$INFOS = "infos.txt";

// on l'ouvre en création
if (!$fic = fopen($INFOS, "w")) {
  print "Erreur d'ouverture du fichier $INFOS en écriture\n";
  exit;
}

// on génère un contenu arbitraire
for ($i = 0; $i < 100; $i++)
  fputs($fic, "login$i:pwd$i:uid$i:gid$i:infos$i:dir$i:shell$i\n");
// on ferme le fichier
fclose($fic);

// on l'exploite - fgets garde la marque de fin de ligne
// cela permet de ne pas récupérer une chaîne vide lors de la lecture d'une ligne blanche
// on l'ouvre en création
if (!$fic = fopen($INFOS, "r")) {
  print "Erreur d'ouverture du fichier $INFOS en lecture\n";
  exit;
}
while ($ligne = fgets($fic, 1000)) {
  // on supprime la marque de fin de ligne si elle existe
  $ligne = cutNewLineChar($ligne);
  // on met la ligne dans un tableau
  $infos = explode(":", $ligne);
  // on récupère le login
  $login = array_shift($infos);
  // on néglige le pwd
  array_shift($infos);
  // on crée une entrée dans le dictionnaire
  $dico[$login] = $infos;
}
// on le ferme
fclose($fic);

// exploitation du dictionnaire
afficheInfos($dico, "login10");
afficheInfos($dico, "X");

// fin
exit;

// --------------------------------------------------------------------------
function afficheInfos($dico, $clé) {
  // affiche la valeur associée à clé dans le dictionnaire $dico si elle existe
  if (isset($dico[$clé])) {
    // valeur existe - est-ce un tableau ?
    $valeur = $dico[$clé];
    if (is_array($valeur)) {
      print "[$clé," . join(":", $valeur) . "]\n";
    } else {
      // $valeur n'est pas un tableau
      print "[$clé,$valeur]\n";
    }
  } else {
    // $clé n'est pas une clé du dictionnaire $dico
    print "la clé [$clé] n'existe pas\n";
  }
}

// --------------------------------------------------------------------------
function cutNewLinechar($ligne) {
  // on supprime la marque de fin de ligne de $ligne si elle existe
  $L = strlen($ligne);  // longueur ligne
  while (substr($ligne, $L - 1, 1) == "\n" or substr($ligne, $L - 1, 1) == "\r") {
    $ligne = substr($ligne, 0, $L - 1);
    $L--;
  }
  // fin
  return($ligne);
}

?>

Le fichier infos.txt :

login0:pwd0:uid0:gid0:infos0:dir0:shell0
login1:pwd1:uid1:gid1:infos1:dir1:shell1
login2:pwd2:uid2:gid2:infos2:dir2:shell2
...
login98:pwd98:uid98:gid98:infos98:dir98:shell98
login99:pwd99:uid99:gid99:infos99:dir99:shell99

Les résultats :

[login10,uid10:gid10:infos10:dir10:shell10]
la clé [X] n'existe pas

Commentaires

  • ligne 11 : fopen(nom_fichier,"w") ouvre le fichier nom_fichier en écriture (w=write). Si le fichier n'existe pas, il est créé. S'il existe, il est vidé. Si la création échoue, fopen rend une valeur false. Dans l'instruction if (!$fic = fopen($INFOS, "w")) {…}, il y a deux opérations successives : 1) $fic=fopen(..) 2) if( ! $fic) {...}
  • ligne 18 : fputs($fic,$chaîne) écrit chaîne dans le fichier $fic.
  • ligne 20 : fclose($fic) ferme le fichier $fic.
  • ligne 25 : fopen(nom_fichier,"r") ouvre le fichier nom_fichier en lecture (r=read). Si l'ouverture échoue (le fichier n'existe pas), fopen rend une valeur false.
  • ligne 29 : fgets($fic,1000) lit la ligne suivante du fichier dans la limite de 1000 caractères. Dans l'opération while ($ligne = fgets($fic, 1000)) {…}, il y a deux opérations successives 1) $ligne=fgets(...) 2) while ( ! $ligne). Après que le dernier caractère du fichier a été lu, la fonction fgets rend la chaîne vide et la boucle while s'arrête.
  • ligne 31 : la fonction fgets lit une ligne de texte, caractère de fin de ligne inclus. La fonction cutNewLineChar ds lignes 70-79 élimine l'éventuel caractère de fin de ligne.
  • ligne 72 : la fonction strlen($chaîne) rend le nombre de caractères de $chaîne.
  • ligne 73 : la fonction substr($ligne, $position, $taille) rend $taille caractères de $ligne, pris à partir du caractère n° $position, le 1er caractère ayant le n° 0. Sur les machines windows, la marque de fin de ligne est "\r\n". Sur les machines Unix, c'est la chaîne "\n".
  • ligne 35 : la fonction array_shift($tableau) élimine le 1er élément de $tableau et le rend comme résultat.
  • ligne 37 : la fonction array_shift($tableau) est utilisée mais on néglige son résultat
  • ligne 57 : la fonction is_array($variable) rend true si $variable est un tableau, false sinon.
  • ligne 58 : la fonction join fait la même chose que la fonction implode déjà rencontrée