Page 1 sur 1

Doc php : pas sûr de comprendre

Posté : 26 août 2011, 20:01
par devlop78
Bonjour à tous, C'est encore moi ;)

http://www.php.net/manual/fr/language.r ... .arent.php
<?php
function foo(&$var) {
$var =& $GLOBALS["baz"];
}
foo($bar);
?>
Ici, la doc explique quelque chose que je ne comprends pas trop. J'ai envie de dire : quel est le problème ? En quoi cela va nous montrer que les ref ne sont pas des pointeurs, et quel rapport avec la fonction ?

Perso, ce que je vois, c'est que dans la fonction, $var se voit attribuer une autre référence que $bar, ... Et que donc si on cherchait, à travers cette fonction, à mettre $bar en référence de $GLOBALS["baz"], c'est raté. Ai-je loupé un truc ? Quelque chose de caché ?

Et d'ailleurs, je trouve que tout est pointeur. Car l'exemple suivant :
<?php

$a = "contenu";
$b = &$a;

$a = "contenu modifié";
unset($a);

echo $b; // On obtient "Contenu modifié"
montre que $b n'est pas un simple alias de $a, puisque si $a disparait, $b devrait pas ressembler à grand chose ... Mais si on explique (sauf erreur de ma part), que $b pointe sur le même zval que $a, j'ai envie de dire : cqfd. On pourrait presque utiliser le noms de pointeur, mais en précisant bien que rien à voir avec la RAM ^^

D'ailleurs drole :
$a = "contenu";
$b = &$a;
$a = &$b;
$a = &$a;
$b = &$b;
Des commentaires ?

Re: Doc php : pas sûr de comprendre

Posté : 26 août 2011, 22:18
par xTG
As-tu lu la page des références arrières ?

Re: Doc php : pas sûr de comprendre

Posté : 26 août 2011, 22:34
par devlop78
Oui pourquoi ?

Re: Doc php : pas sûr de comprendre

Posté : 27 août 2011, 10:19
par xTG
As-tu testé l'exemple alors ? ^^'
Je ne pense pas, sinon tu aurais tout de suite compris. #-o

$bar contient une référence vers $var, qui elle contient une référence sur une variable globale.
Sauf que $var est déclarée à l'intérieur d'une fonction, ce qui fait qu'elle est inaccessible à l'extérieur, mais surtout n'est pas présente dans la table des symboles !

Ce bout de code là :
<?php
function foo(&$var) {
  $var =& $_GET["baz"];
}
$bar = "toto";
foo($bar);
echo $bar;
?>
Affichera donc ,quelque soit la valeur dans $_GET['baz'] , toto ! ;)

Pour résoudre cela il faut utiliser une référence arrière pour obtenir la comportement voulu.

Re: Doc php : pas sûr de comprendre

Posté : 27 août 2011, 21:13
par devlop78
Ce que tu me donnes est exactement le même que l'exemple que j'avais montré. Et je ne vois aucun rapport avec le fait que ce soit une variable globale ou non. Et oui, j'ai bien testé, je n'ai eu aucune surprise.

$var =& $_GET["baz"];

Que tu sois dans une fonction ou pas, tu modifies le pointeur de $var vers $_GET["baz"]; Il n'y a donc, à ce moment, plus de liens entre $var et $bar, quelque soit le scope. C'est la meilleure explication que j'ai trouvé, et je trouve ça logique.
$_GET["baz"] = "momo";

function foo(&$var) {
$var =& $_GET["baz"];
}
$bar = "toto";
foo($bar);
echo $bar; // Affiche toto
$_GET["baz"] = "momo";

function foo(&$var) {
$var =& $_GET["baz"];
}
$bar = "toto";
$var = &$bar;
$var =& $_GET["baz"];
echo $bar;
Qu'est ce que tu appelles table des symboles ? Quel rapport ?

D'ailleurs je n'avais pas compris ça :
<?php
$var1 = "Variable Exemple";
$var2 = "";

function global_references($use_globals)
{
global $var1, $var2;
if (!$use_globals) {
$var2 =& $var1; // visible uniquement dans la fonction
} else {
$GLOBALS["var2"] =& $var1; // visible également dans un contexte global
}
}

global_references(false);
echo "var2 est défini à '$var2'\n"; // var2 est défini à ''
global_references(true);
echo "var2 est défini à '$var2'\n"; // var2 est défini à 'Variable Exemple'
?>
Car je me disais que tu faisais un lien entre $var2 et $var1. Mais la lecture suivante explique tout (et c'est d'ailleurs hyper logique) :
Lorsque vous déclarez une variable global $var, vous créez en fait une référence sur une variable globale. Ce qui signifie que

<?php
$var =& $GLOBALS["var"];
?>
Tu as modifies donc le pointeur de $var2 (oui effectivement, le $var2 de la fonction) sur le $var1 (et donc sur $var1 global). Mais du coup, $var2 global n'est pas affecté.

Bref, j'ai toujours l'impression d'avoir bien compris ;) Mais "la table des symboles", ça reste un peu chinois pour moi.

Re: Doc php : pas sûr de comprendre

Posté : 28 août 2011, 12:42
par xTG
La tale des symboles c'est ce qui est accessible, on y retrouve des fonctions, des variables, etc.

Par contre tu n'as pas encore compris, et ce même mon message. :/
$bar pointe vers $var qui pointe vers $GLOBAL.
Et non $bar ne pointe pas directement vers $GLOBAL ! Auquel cas il n'y aurait aucun problème...
Ce qui fait que comme $var n'est pas accessible (car locale à la fonction) tu casses le lien.

Re: Doc php : pas sûr de comprendre

Posté : 28 août 2011, 14:13
par devlop78
Oui ... Toujours pas compris ;) Enfin, ce que j'en ai compris,à chaque fois que je fais des tests j'ai bon sur ce que je pense qu'il va se passer ... Or là, le seul truc que je vois c'est que $var switche vers $GLOBAL['baz'] donc forcément n'est plus en relation avec $bar. Donc forcément $bar n'aura en aucun cas changé.

Dès le départ, la documentation (et ce n'est pas la première fois) n'est pas toujours bien construire, même si ça reste une bible dans la matière :
Il va se passer que $var dans foo sera lié à $bar, mais il sera aussi relié à $GLOBALS["baz"].
Tout simplement, je démontre que c'est faux (que il n'est pas lié en même temps) :
$a = 'mdr';
$b = 'lol';
$c = &$a;
$c = &$b;
$c = 'je suis c';
var_dump(array($a,$b,$c));
$c n'est plus relié à $a.
Il n'y a pas moyen de lier $bar à quelque chose d'autre en utilisant le mécanisme de référence, car $bar n'est pas accessible dans la fonction foo
Je suis d'accord, mais leur exemple n'essaie même pas de le faire, puisque qu'il essaie de relier une référence à autre chose. Donc comme le montre le précedent exemple, ce n'est pas possible. Ici, j'avais tout à fait compris et je l'ai dit.
(certes, il est représenté par $var et $var possède la même valeur, mais n'est pas relié par la table des symboles)
S'ils le disent. Pour moi c'est du chinois. Déjà $var n'a pas la même valeur, il pointe sur le même contenu. C'est différent même si le résultat est le même sur un echo. Mais alors le coup d'être relié par la table des symboles ... Là je ne pige pas. Il me faudrait la voir cette table ...
Vous pouvez utiliser les références arrières pour référencer les variables sélectionnées par la fonction.
N'est pas une explication ici, juste une solution à un problème qui n'en était pas un. A aucun moment je ne m'attendais à ce que $bar soit lié à $GLOBAL['baz']

Bref, la différence avec les pointeurs en C n'est pas vraiment démontrée, même si ils ne pointent pas sur le même type de contenu, et que les pointeurs sont typés et qu'on peut tantôt lire leur valeur (un integer représentant l'adresse mémoire), tantôt lire la valeur sur laquelle ils pointent. Peut-être qu'en C, écrit un peu différemment, $bar se changerait en pointeur pour pointer sur $GLOBAL['baz'], j'ai quand même un petit doute ;) mais je trouve que la comparaison est quand même possible puisqu'une variable n'est jamais qu'une adresse pointant vers un contenu, à la différence de C, que l'on ne gère rien. Encore heureux...

Re: Doc php : pas sûr de comprendre

Posté : 28 août 2011, 14:17
par devlop78
D'ailleurs, il s'agit d'un problème de traduction :
What happens is that $var in foo will be bound with $bar in the caller, but then re-bound with $GLOBALS["baz"].
Je suis pas doué en anglais, mais ils disent bien "then re-bound", comme quoi $var change vraiment de référence, et en aucun cas ne pointe sur deux contenus simultanément. Je pense que leur texte ne veut pas dire grand chose à cause de la traduction.

Re: Doc php : pas sûr de comprendre

Posté : 29 août 2011, 11:31
par xTG
Beh...
$bar pointe vers $var.
Dans la fonction on accède à la valeur de $var (et donc celle de $bar).
On y mets un pointeur vers $GLOBAL.
Donc $bar pointe vers $GLOBAL.

Et non comme tu le dit que c'est $var qui pointe vers $bar.

Ou alors j'ai jamais rien capté aux pointeurs malgré les avoir utilisé depuis tout ce temps. :priere:

Re: Doc php : pas sûr de comprendre

Posté : 29 août 2011, 12:12
par popy
Il faut plus voir ça comme deux opérateurs différents (et bien comprendre que $toto n'est pas une variable mais un symbole, qui pointe vers une variable):

L'opérateur = (qui change la valeur de la variable), et l'opérateur =& (qui fait pointer vers une variable)

$b =& $a; fait que le symbole "$b" pointe vers la même variable que le symbole "$a".

$b =& $c; fait que $b pointe maintenant vers $c, sans changer la valeur de $a.

$b = 'toto'; fait que la valeur de la variable pointée par $b change, pour devenir 'toto'. Comme $b et $c pointent vers la même variable, echo $c; affichera 'toto'.

Enfin, la fonction unset ne détruit pas une variable, mais un symbole. Donc unset($b); fait que $b n'est pas utilisable, mais la valeur qu'il pointait reste inchangée, et ne sera détruite que si aucun symbole n'y fait référence (si on fait unset($c) par exemple).

Par contre (oublions les deux unset précédents), $b = null; change la valeur de la variable pointée par $b, donc $b et $c pointent toujours vers une même variable qui vaut maintenant null. Si par la suite on fait $c = 'toto';, $b et $c valent de nouveau 'toto'.


Attention cependant avec les références explicites vers des objets !!! Explications

Code : Tout sélectionner

$a = new toto(); $b = $a;
Ici, le symbole $b pointe bien vers une variable différente de $a, MAIS la valeur de cette variable est elle même une sorte de pointeur vers l'objet (référence implicite donc). Si maintenant on fait $b = null; ou encore unset($b), $a pointe toujours vers le "pointeur" de notre objet.

Compliquons un peu, pour que ça devienne amusant :
$a = new toto();
$b= $a;
$c =& $a;
Ici, on a $a et $c qui pointent vers la même variable, qui est un "pointeur" vers notre objet. $b pointe vers sa propre variable, qui est elle aussi un pointeur vers l'objet. Donc si on fait $a = null;, $a et $c pointent vers une variable de valeur "null", l'objet n'est pas modifié pour le moment.
Si on avait fait $b = null; la variable pointée par $b serait devenue une variable contenant null, à la place du pointeur. Toujours pas de changement pour l'objet.
Si on avait fait unset($b);, $b n'existant plus, la variable qu'il pointait n'est plus référencée donc est détruite. Le pointeur vers l'objet est donc détruit mais l'objet reste intact.


Maintenant évidement, si on fait :
unset($a);
unset($b);
unset($c);
Ou
$a = null;
unset($b);
Toutes les références vers notre objet vont être détruites, donc l'objet va être détruit.

Re: Doc php : pas sûr de comprendre

Posté : 29 août 2011, 20:43
par popy
Personne ne répond parce que c'est affligeant ou parce que c'est parfait ? :]

Re: Doc php : pas sûr de comprendre

Posté : 29 août 2011, 23:27
par filoucrackeur
ca tamuse de faire choffé mes pauvres neurones que je commence a perdre pour traquer la moindre anomalie que tu aurai pu commaitre ;) hein popy

Re: Doc php : pas sûr de comprendre

Posté : 30 août 2011, 00:06
par popy
Y a pas d'erreur :p

Re: Doc php : pas sûr de comprendre

Posté : 30 août 2011, 03:21
par devlop78
Je suis totalement d'accord avec Popy. Et oui j'avais mal compris l'explication de php.net tout simplement parce que la traduction est erronée (je comprends celle en anglais ...). Dire que $a pointe vers $b est de toutes façons une "abération", je vois les choses en zval (ce que popy semble appeler "variable" alors que j'appelle variable ce que popy appelle symbole, mais d'un point de vue zval, les symboles peuvent être appelés pointeurs). Bref, rien ne contredit mon premier post (sauf si j'ai inversé $bar et $var dans mon texte, mais au fond, ça revient au même puisque ils ne pointent pas l'un vers l'autre mais vers un contenu).

Je pense donc que je peux fermer le post. D'ailleurs, petite précision : dans la page "ce que les références ne sont pas", "références arrières" est une bien mauvaise expression, puisque l'anglais est "returning references" ou comment une fonction/méthode peut retourner une référence. Tout comme "mais il sera aussi relié" de l'anglais "but then re-bound" : le "aussi" est de trop. Cela indique que la variable (ou symbole) pointe sur deux contenus simultanément.

Merci pour votre participation.