Les référencesQu'est ce qu'une référence ?
En PHP, les références sont un moyen d'accéder au contenu d'une même
variable en utilisant plusieurs noms. Les références ne sont pas comme des
pointeurs en C : vous ne pouvez pas effectuer d'opération arithmétique de pointeurs
sur celles-ci, ce ne sont pas des adresses mémoires, etc.
Vous pouvez consulter
pour plus d'informations.
En fait, les références sont des alias dans la table des symboles.
Notez qu'en PHP, le nom d'une variable et son contenu sont deux
notions distinctes, ce qui fait que l'on peut donner
plusieurs noms au même contenu.
On peut faire l'analogie avec les fichiers sous Unix, et leur noms :
les noms des variables sont les entrées dans un répertoire, tandis
que le contenu de la variable est le fichier en lui-même.
Les références en PHP peuvent alors être considérées comme semblables
aux liens sous Unix.
Que font les références ?
Il existe trois principales utilisations des références :
l'assignation par
référence, le passage
par référence,
et le retour par
référence. Cette section va introduire ces opérations, avec des liens
vers plus de précisions.
Assignation par référence
Dans ce premier cas, les références PHP permettent de faire en
sorte que deux variables référencent le même contenu.
Par exemple :
]]>
Cette écriture indique que $a et $b
pointent sur le même contenu.
$a et $b sont complètement
égales ici : ce n'est pas $a qui pointe sur
$b, ou vice-versa. Ce sont bien $a
et $b qui pointent sur le même contenu.
Si vous assignez, passez, ou retournez, une variable indéfinie par référence,
elle sera créée automatiquement.
Utilisation des références avec des variables indéfinies
d);
var_dump(property_exists($c, 'd')); // bool(true)
?>
]]>
La même syntaxe peut être utilisée avec les fonctions qui
retournent des références :
]]>
Utiliser la même syntaxe avec une fonction qui ne
retourne par référence génèrera une erreur, comme l'utiliser avec le
résultat de l'opérateur new.
Tant bien que les objets sont passés comme des pointeurs, ceci n'est pas
identique au références comm expliqué dans la section les
Objets et références.
Si vous assignez une référence à une variable déclarée comme global
dans une fonction, la référence ne sera visible qu'au sein de la fonction.
Vous pouvez éviter cela en utilisant le tableau $GLOBALS.
Référencer des variables globales depuis des fonctions
]]>
Voyez global $var; comme un raccourci pour $var
=& $GLOBALS['var'];. De ce fait, assigner une autre référence à
$var modifie uniquement la référence locale de la variable.
Si vous assignez une valeur à une variable qui a des références dans une structure
&foreach;, les références seront également modifiées.
Références et structure foreach
]]>
Même si ce n'est pas strictement une assignation par référence, les expressions
créées avec la structure de langage
array() peuvent aussi
se comporter comme telles, en préfixant par & l'élément du tableau.
Voici un exemple :
]]>
Notez par contre que les références à l'intérieur des tableaux peuvent s'avérer
dangereuses. Utiliser une assignation normale (pas par référence) avec une
référence à droite de l'opérateur ne transforme pas la partie gauche de l'assignation
en référence, mais les références à l'intérieur des tableaux sont préservées. Ceci
s'applique également aux appels de fonctions avec un tableau passé par valeur.
Exemple :
]]>
Autrement dit, d'un point de vue des références, le comportement des tableaux
est défini élément par élément ; le comportement de chaque élément
est indépendant du statut de référence du tableau qui les contient.
Passage par référence
Le deuxième intérêt des références est de
permettre de passer des variables par référence. On réalise ceci en faisant
référencer le même contenu par une variable locale à un fonction et par une
variable du contexte appelant.
Par exemple :
]]>
Après l'exécution de cette portion de code, $a vaut 6.
Cela provient du fait que, dans la fonction foo, la
variable $var pointe sur le même contenu que
$a.
Pour plus d'informations à ce sujet, vous pouvez consulter la section
passage par référence.
Retour par référence
Le troisième intérêt des références est de permettre le
retour de valeurs par
référence.
Ce que les références ne sont pas
Comme nous l'avons vu précédemment, les références ne
sont pas des pointeurs. Cela signifie que le script suivant ne fera pas
ce à quoi on peut s'attendre :
]]>
Ici, la variable $var dans la fonction foo sera liée
à $bar dans l'appelant, mais elle sera ensuite reliée à
$GLOBALS["baz"].
Il n'est pas possible de lier $bar à quelque chose d'autre en utilisant
le mécanisme de références, car $bar n'est pas accessible dans la
fonction foo (certes, elle est représentée par $var,
mais $var ne fait référence qu'à la valeur, et n'a pas de liaison dans
la table de symboles de l'appelant).
Vous pouvez utiliser le retour par
référence pour référencer des variables sélectionnées par la fonction.
Passage par référence
Vous pouvez passer une variable par référence à une fonction, de
manière à ce que celle-ci puisse la modifier.
La syntaxe est la suivante :
]]>
Il n'y a pas de signe de référence dans l'appel de la
fonction, uniquement sur sa définition. La définition de la
fonction en elle-même est suffisante pour passer correctement
des arguments par référence.
Les données suivantes peuvent être passées par référence :
Une variable, comme dans foo($a)
Une référence retournée par une fonction :
]]>
Pour plus d'informations, voir les détails dans
retour par
référence.
Toutes les autres expressions ne doivent pas être passées par
référence, car le résultat sera indéfini. Par exemple,
les passages par référence suivants sont invalides :
]]>
Retourner des références
Retourner des références est utile lorsque vous
voulez utiliser une fonction pour déterminer à quelle variable
une référence devrait être liée.
N'utilisez pas
le retour par référence pour améliorer les performances,
le moteur est suffisamment robuste pour optimiser cela
en interne. Retournez des références uniquement
lorsque vous avez de bonnes raisons techniques
de le faire ! Pour retourner des références, utilisez cette syntaxe :
value;
}
}
$obj = new foo;
$myValue = &$obj->getValue(); // $myValue est une référence de $obj->value, qui vaut 42.
$obj->value = 2;
echo $myValue; // affiche la nouvelle valeur de $obj->value, i.e. 2.
?>
]]>
Dans cet exemple, on affecte une valeur à la propriété de l'objet
retourné par la fonction getValue, et non à sa copie,
comme ce serait le cas si nous n'avions pas utilisé la syntaxe de référence.
Contrairement au passage de paramètre, ici, vous devez utiliser
& aux deux endroits, à la fois pour
indiquer que vous retournez par référence (pas par copie), et
pour indiquer que vous assignez aussi par référence (pas par copie
non plus) pour la variable $myValue.
Si vous tentez de retourner une référence depuis une fonction
avec la syntaxe : return ($this->value);,
cela ne fonctionnera pas comme
vous l'attendez, et retournera le résultat de l'expression,
et pas de la variable, par référence. Vous ne pouvez retourner que
des variables par référence depuis une fonction - et rien d'autre.
Pour utiliser la référence retournée, vous devez utiliser l'affectation
par référence :
]]>
Pour passer la référence retournée à une autre fonction attendant une référence,
vous pouvez utiliser la syntaxe suivante :
]]>
Notez que array_push(&collector(), 'foo');ne fonctionnera pas, et résultera en une erreur
fatale.
Détruire une référence
Lorsque vous détruisez une référence, vous ne
faites que casser le lien entre le nom de la variable et son contenu.
Cela ne signifie pas que le contenu de la variable est détruit.
Par exemple :
]]>
Cet exemple ne détruira pas $b, mais juste
$a.
Encore une fois, on peut comparer cette action avec l'appel
unlink d'Unix.
Repérer une référence
De nombreuses syntaxes de PHP sont implémentées via le
mécanisme de référence, et tout ce qui a
été vu concernant les liaisons entre variables
s'applique à ces syntaxes. Certaines constructions, comme le passage
d'arguments et le retour par référence, ont été mentionnées plus haut.
D'autres constructions qui utilisent les références sont les suivantes :
Références globales
Lorsque vous déclarez une variable en tant que global $var,
vous créez en fait une référence sur une variable
globale. Autrement dit, cela revient au même que :
]]>
Cela signifie aussi que détruire la variable $var n'entrainera
pas la destruction de la variable globale.