Port�e des variables
La port�e d'une variable d�pend du contexte dans lequel la variable est d�finie. Pour la majorit� des variables, la port�e concerne la totalit� d'un script PHP. Mais, lorsque vous d�finissez une fonction, la port�e d'une variable d�finie dans cette fonction est locale � la fonction. Par exemple :
Exemple #1 Les variables sont locales � la fonction
<?php
$a = 1;
include 'b.inc';
?>
Ici, la variable $a sera accessible dans le script inclus b.inc. Cependant, dans les fonctions d�finies par l'utilisateur, une nouvelle d�finition de cette variable sera donn�e, limit�e � la fonction. Toute variable utilis�e dans une fonction est, par d�finition, locale. Par exemple :
<?php
$a = 1; /* port�e globale */
function test()
{
echo $a; /* port�e locale */
}
test();
?>
Le script n'affichera rien � l'�cran car l'instruction echo() utilise la variable locale $a, et celle-ci n'a pas �t� assign�e pr�alablement dans la fonction. Vous pouvez noter que ce concept diff�re un petit peu du langage C dans lequel une variable globale est automatiquement accessible dans les fonctions, � moins d'�tre red�finie localement dans la fonction. Cela peut poser des probl�mes si vous red�finissez des variables globales localement. En PHP, une variable globale doit �tre d�clar�e � l'int�rieur de chaque fonction afin de pouvoir �tre utilis�e dans cette fonction.
Le mot cl� global
Commen�ons par un exemple avec global :
Exemple #2 Exemple avec global
<?php
$a = 1;
$b = 2;
function somme() {
global $a, $b;
$b = $a + $b;
}
somme();
echo $b;
Le script ci-dessus va afficher la valeur 3. En d�clarant globales les variables $a et $b locales de la fonction somme(), toutes les r�f�rences � ces variables concerneront les variables globales. Il n'y a aucune limite au nombre de variables globales qui peuvent �tre manipul�es par une fonction.
Une deuxi�me m�thode pour acc�der aux variables globales est d'utiliser le tableau associatif pr�-d�fini $GLOBALS. Le pr�c�dent exemple peut �tre r��crit de la mani�re suivante :
Exemple #3 Les variables globales et $GLOBALS
<?php
$a = 1;
$b = 2;
function somme() {
$GLOBALS['b'] = $GLOBALS['a'] + $GLOBALS['b'];
}
somme();
echo $b;
?>
Le tableau $GLOBALS est un tableau associatif avec le nom des variables globales comme cl� et les valeurs des �l�ments du tableau comme valeur des variables. Notez que $GLOBALS existe dans tous les contextes, car $GLOBALS est un superglobal. Voici un exemple des super globaux :
Exemple #4 Les variables super globales
<?php
function test_global() {
// La plupart des variables pr�-d�finies ne sont pas des "superglobales" et
// requi�rent le mot-cl� 'global' pour �tre disponibles dans une fonction.
global $HTTP_POST_VARS;
echo $HTTP_POST_VARS['name'];
// Les superglobales sont accessibles dans tous les contextes
// et ne requi�rent pas 'global'. Les superglobales sont disponibles
// depuis PHP 4.1.0 et HTTP_POST_VARS est de plus en plus
// d�pr�ci�.
echo $_POST['name'];
}
?>
Utilisation des variables static
Une autre caract�ristique importante de la port�e des variables est la notion de variable static. Une variable statique a une port�e locale uniquement, mais elle ne perd pas sa valeur lorsque le script appelle la fonction. Prenons l'exemple suivant :
Exemple #5 Les variables statiques
<?php
function test()
{
$a = 0;
echo $a;
$a++;
}
?>
Cette fonction est un peu inutile car � chaque fois qu'elle est appel�e, elle initialise $a � 0 et affiche "0". L'incr�mentation de la variable ($a++) ne sert pas � grand chose, car d�s que la fonction est termin�e, la variable $a dispara�t. Pour faire une fonction de comptage utile, c'est-�-dire qui ne perdra pas la trace du compteur, la variable $a est d�clar�e comme une variable statique :
Exemple #6 Les variables statiques (2)
<?php
function test()
{
static $a = 0;
echo $a;
$a++;
}
?>
Maintenant, la variable $a est initialis�e uniquement lors du premi�re appel � la fonction et, � chaque fois que la fonction test() est appel�e, elle affichera une valeur de $a incr�ment�e de 1.
Les variables statiques sont essentielles lorsque vous faites des appels r�cursifs � une fonction. Une fonction r�cursive est une fonction qui s'appelle elle-m�me. Il faut faire attention lorsque vous �crivez une fonction r�cursive car il est facile de faire une boucle infinie. Vous devez v�rifier que vous avez bien une condition qui permet de terminer votre r�cursivit�. La fonction suivante compte r�cursivement jusqu'� 10, en utilisant la variable $count pour savoir quand il faut s'arr�ter :
Exemple #7 Les variables statiques et la r�cursivit�
<?php
function test()
{
static $count = 0;
$count++;
echo $count;
if ($count < 10) {
test();
}
$count--;
}
?>
Note: Les variables statiques doivent �tre d�clar�es comme dans l'exemple ci-dessus. Tenter d'assigner des valeurs � ces variables qui sont le r�sultat d'expressions causera une erreur d'analyse.
Exemple #8 D�claration de variables statiques
<?php
function foo(){
static $int = 0; // correct
static $int = 1+2; // faux (car c'est une expression)
static $int = sqrt(121); // faux (car c'est aussi une expression)
$int++;
echo $int;
}
?>
Les r�f�rences avec les variables global et static
Le Zend Engine 1, sur qui repose PHP 4, impl�mente les options static et global pour les variables, en terme de r�f�rence. Par exemple, une vraie variable globale est import�e dans un contexte de fonction avec global. Cette commande cr�e en fait une r�f�rence sur la variable globale. Cela peut vous mener � des comportements inattendus, par exemple :
<?php
function test_global_ref() {
global $obj;
$obj = &new stdclass;
}
function test_global_noref() {
global $obj;
$obj = new stdclass;
}
test_global_ref();
var_dump($obj);
test_global_noref();
var_dump($obj);
?>
L'exemple ci-dessus va afficher :
NULL
object(stdClass)(0) {
}
Un comportement similaire s'applique � la commande static. Les r�f�rences ne sont pas stock�es dynamiquement :
<?php
function &get_instance_ref() {
static $obj;
echo 'Objet statique : ';
var_dump($obj);
if (!isset($obj)) {
// Assigne une r�f�rence � une variable statique
$obj = &new stdclass;
}
$obj->property++;
return $obj;
}
function &get_instance_noref() {
static $obj;
echo 'Objet statique : ';
var_dump($obj);
if (!isset($obj)) {
// Assigne une objet � une variable statique
$obj = new stdclass;
}
$obj->property++;
return $obj;
}
$obj1 = get_instance_ref();
$still_obj1 = get_instance_ref();
echo "\n";
$obj2 = get_instance_noref();
$still_obj2 = get_instance_noref();
?>
L'exemple ci-dessus va afficher :
Objet statique : NULL
Objet statique : NULL
Objet statique : NULL
Objet statique : object(stdClass)(1) {
["property"]=>
int(1)
}
Ces exemples illustrent les probl�mes rencontr�s lors de l'assignation de r�f�rence � des variables statiques, qui sont oubli�es lorsque vous appelez &get_instance_ref() une seconde fois.