Changement dans la gestion des r�f�rences
Pr�sentation
Du point de vue du programmeur, le changement qui aura le plus d'impact sur le code d�j� �crit est la mani�re avec laquelle les r�f�rences sont g�r�es dans les versions PHP 4.4.0 et plus r�centes.
Jusqu'� la version PHP 4.3 incluse, il �tait possible d'envoyer, assigner ou retourner des variables par r�f�rences, alors qu'elles auraient dues �tre retourn�es par valeur, comme des constantes, des valeurs temporaires (comme le r�sultat d'une expression), ou le r�sultat d'une fonction qui elle-m�me, retourne une valeur.
<?php
$foo = "123";
function return_value() {
global $foo;
return $foo;
}
$bar = &return_value();
?>
M�me si ce code fonctionne tel qu'attendu en PHP 4.3, en g�n�ral il conduit � une situation ind�finie. Le moteur Zend ne peut pas fonctionner correctement avec des valeurs pass�es par r�f�rences. Ce bogue peut et a conduit � des corruptions de m�moire difficiles � reproduire, notamment lorsque le code de l'application est compliqu�.
En PHP 4.4.0, PHP 5.0.4 et toutes les versions plus r�centes, le moteur Zend a �t� modifi� pour reconna�tre les cas o� une valeur ne doit pas �tre utilis�e par r�f�rence. La valeur r�elle est maintenant utilis�e dans ces cas, et une alerte est �mise. Cette alerte prend la forme d'un message E_NOTICE en PHP 4.4.0 et plus r�cent, et E_STRICT en PHP 5.0.4 et plus r�cent.
Du code qui pouvait produire des corruptions de m�moire ne peut plus le faire. Cependant, certains codes anciens peuvent fonctionner de mani�re diff�rente.
Code qui fonctionnait en 4.3.x, mais qui �choue maintenant
<?php
function func(&$arraykey) {
return $arraykey; // la fonction retourne par valeur!
}
$array = array('a', 'b', 'c');
foreach (array_keys($array) as $key) {
$y = &func($array[$key]);
$z[] =& $y;
}
var_dump($z);
?>
<
L'ex�cution du script ci-dessus dans une version de PHP ant�rieure � la correction du bogue produit ce r�sultat :
array(3) { [0]=> &string(1) "a" [1]=> &string(1) "b" [2]=> &string(1) "c" }
Apr�s la correction du bogue, cela donne :
array(3) { [0]=> &string(1) "c" [1]=> &string(1) "c" [2]=> &string(1) "c" }
Ceci est d� au fait que func() effectue une assignation par valeur. La valeur de $y est r�assign�e, et que la liaison par r�f�rence avec $z est pr�serv�e. Avant la correction du bogue, la valeur �tait assign�e par r�f�rence, faisant que la variable $y �tait r�assign�e � chaque assignement. La tentative de liaison avec une valeur temporaire est la cause de la corruption de la m�moire.
Ce code peut �tre r�par� pour fonctionner � l'identique avec des versions pr� et post-correction. La signature de func() peut �tre modifi�e pour retourner les valeurs par r�f�rence, ou bien l'affectation par r�f�rence peut �tre supprim�e du r�sultat de func().
<?php
function func() {
return 'function return';
}
$x = 'original value';
$y =& $x;
$y = &func();
echo $x;
?>
En PHP 4.3, $x vaudrait 'original value', alors qu'apr�s le changement, il vaudrait 'function return' : n'oubliez pas que la fonction ne retourne plus par r�f�rence, et que la r�f�rence est convertie en affectation par valeur. Encore une fois, cela peut �tre corrig� en for�ant func() � retourner par r�f�rence, ou bien en �liminant l'affectation par r�f�rence.
Code qui fonctionnait en PHP 4.3.x, mais qui �met maintenant une erreur
<?php
class Foo {
function getThis() {
return $this;
}
function destroyThis() {
$baz =& $this->getThis();
}
}
$bar = new Foo();
$bar->destroyThis();
var_dump($bar);
?>
En PHP 5.0.3, $bar vaut NULL au lieu de l'objet attendu. Cela arrive car getThis() retourne une valeur, mais que la valeur est assign�e par r�f�rence. M�me si cela fonctionne d�sormais comme attendu, ce code est en fait invalide, et �mettra une alerte E_NOTICE sous PHP 4.4 ou E_STRICT en PHP 5.0.4 et plus r�cent.
Code qui �chouaient en PHP 4.3.x, mais qui fonctionne maintenant
<?php
function &f() {
$x = "foo";
var_dump($x);
print "$x\n";
return($a);
}
for ($i = 0; $i < 3; $i++) {
$h = &f();
}
?>
En PHP 4.3, le troisi�me appel � var_dump() produit NULL, � cause d'une correction de la m�moire, caus�e par le retour d'une valeur non initialis�e par r�f�rence. C'est du code valide en PHP 5.0.4 et plus r�cent, mais il produit une erreur dans les versions plus anciennes.
<?php
$arr = array('a1' => array('alfa' => 'ok'));
$arr =& $arr['a1'];
echo '-'.$arr['alfa']."-\n";
?>
Jusqu'en PHP 5.0.5, il n'�tait pas possible d'assigner un �l�ment de tableau par r�f�rence de cette mani�re. C'est corrig� maintenant.
Code qui aurait du fonctionner en PHP 5.0.x
Il y a quelques cas de bogues rapport�s en PHP PHP 5.0 avant la correction de ce bogue qui 'refonctionnent'. Cependant, dans tous les cas, des erreurs sont �mises en PHP 5.1.x, car le code est invalide. Retourner des r�f�rences avec self:: fonctionne maintenant, mais �met une alerte E_STRICT, et m�me si votre exp�rience est diff�rente lors de l'assignation d'un objet par r�f�rence, vous verrez toujours une erreur E_ERROR lorsque vous tentez cela m�me si l'assignation semble fonctionner.
Alertes qui vont et viennent
Des appels imbriqu�s � des fonctions retournant des valeurs par r�f�rence sont valides en PHP 4.3.x et PHP 5.1.x, mais ils �mettent des erreurs E_NOTICE et E_STRICT dans les nouvelles versions de PHP.
<?php
function & foo() {
$var = 'ok';
return $var;
}
function & bar() {
return foo();
}
$a =& bar();
echo "$a\n";
?>