downloads | documentation | faq | getting help | mailing lists | licenses | wiki | reporting bugs | php.net sites | links | conferences | my php.net

search for in the

Ce que les références ne sont pas> <Qu'est ce qu'une référence ?
Last updated: Fri, 14 Aug 2009

view this page in

Que font les références ?

Les références vous permettent de faire pointer deux variables sur le même contenu. Par exemple, lorsque vous faites :

Exemple #1 Les références

<?php
$a 
=& $b;
?>

cela signifie que $a et $b pointent sur le même contenu.

Note: $a et $b sont complètement égales ici : ce n'est pas $a qui pointe sur $b, ou vice-versa. C'est bien $a et $b qui pointent sur le même contenu.

Note: Si un tableau par référence est copié, ses valeurs ne sont pas déréférencées. Cela est valide également pour les tableaux passés par valeur aux fonctions.

Note: Si vous assignez, passez ou retournez une variable indéfinie par référence, elle sera créée automatiquement.

Exemple #2 Utilisation des références avec des variables indéfinies

<?php
function foo(&$var) { }

foo($a); // $a est "créée" et assignée à NULL

$b = array();
foo($b['b']);
var_dump(array_key_exists('b'$b)); // bool(true)

$c = new StdClass;
foo($c->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, et avec l'opérateur new (PHP 4.0.4 et plus récent) :

<?php
$bar 
=& new fooclass();
$foo =& find_var($bar);
?>

Depuis PHP 5, new retourne une référence automatiquement, donc, l'utilisation de =& dans ce contexte est obsolète et produit un message de niveau E_STRICT.

Note: Le fait de ne pas utiliser l'opérateur & produit une copie de l'objet. Si vous utilisez $this dans la classe, il fonctionnera dans l'instance courante de la classe. L'assignement sans l'opérateur & copiera l'instance (i.e. l'objet) et $this fonctionnera sur cette copie, ce qui n'est pas toujours le comportement désiré. Habituellement, vous voulez avoir une seule instance afin de préserver les performances et la consommation mémoire.
Même si vous pouvez utiliser l'opérateur @ pour supprimer les messages d'erreurs du constructeur avec la syntaxe @new, cela ne fonctionnera pas avec la syntaxe &new. C'est une limitation du moteur Zend, et cela conduit à une erreur d'analyse.

Avertissement

Si vous assignez une référence à une variable définie en tant que global dans une fonction, la référence sera visible uniquement à l'intérieure de la fonction. Vous pouvez éviter cela en utilisant le tableau $GLOBALS.

Exemple #3 Référencer une variable globale à l'intérieure d'une fonction

<?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'
?>

Voyez global $var; comme un raccourci pour $var =& $GLOBALS['var'];. De ce fait assignant d'autres références à $var changeant uniquement la référence locale de la variable.

Note: Si vous assignez des valeurs par références dans une structure foreach, les références seront également modifiées.

Exemple #4 Références et structure foreach

<?php
$ref 
0;
$row =& $ref;
foreach (array(
123) as $row) {
    
// faites quelque chose
}
echo 
$ref// 3 - le dernier élément du tableau itéré
?>


Le deuxième intérêt des références est de pouvoir passer des variables par référence. On réalise ceci en faisant pointer des variables locales vers le contenu des variables de fonction. Exemple :

Exemple #5 Passage de paramètre par référence

<?php
function foo(&$var) {
  
$var++;
}
$a=5;
foo($a);
?>

$a vaut 6. Cela provient du fait que dans la fonction foo, la variable $var pointe sur le même contenu que $a. Voir aussi les explications détaillées dans passage par référence.

Le troisième intérêt des références est de retourner des valeurs par référence.



add a note add a note User Contributed Notes
Que font les références ?
strata_ranger at hotmail dot com
26-Sep-2009 10:29
An interesting if offbeat use for references:  Creating an array with an arbitrary number of dimensions.

For example, a function that takes the result set from a database and produces a multidimensional array keyed according to one (or more) columns, which might be useful if you want your result set to be accessible in a hierarchial manner, or even if you just want your results keyed by the values of each row's primary/unique key fields.

<?php
function array_key_by($data, $keys, $dupl = false)
/*
 * $data  - Multidimensional array to be keyed
 * $keys  - List containing the index/key(s) to use.
 * $dupl  - How to handle rows containing the same values.  TRUE stores it as an Array, FALSE overwrites the previous row.
 *         
 * Returns a multidimensional array indexed by $keys, or NULL if error.
 * The number of dimensions is equal to the number of $keys provided (+1 if $dupl=TRUE).
 */  
{
   
// Sanity check
   
if (!is_array($data)) return null;
   
   
// Allow passing single key as a scalar
   
if (is_string($keys) or is_integer($keys)) $keys = Array($keys);
    elseif (!
is_array($keys)) return null;

   
// Our output array
   
$out = Array();
   
   
// Loop through each row of our input $data
   
foreach($data as $cx => $row) if (is_array($row))
    {
     
     
// Loop through our $keys
     
foreach($keys as $key)
      {
       
$value = $row[$key];

        if (!isset(
$last)) // First $key only
       
{
          if (!isset(
$out[$value])) $out[$value] = Array();
         
$last =& $out; // Bind $last to $out
       
}
        else
// Second and subsequent $key....
       
{
          if (!isset(
$last[$value])) $last[$value] = Array();
        }

       
// Bind $last to one dimension 'deeper'.
        // First lap: was &$out, now &$out[...]
        // Second lap: was &$out[...], now &$out[...][...]
        // Third lap:  was &$out[...][...], now &$out[...][...][...]
        // (etc.)
       
$last =& $last[$value];
      }
     
      if (isset(
$last))
      {
       
// At this point, copy the $row into our output array
       
if ($dupl) $last[$cx] = $row; // Keep previous
       
else       $last = $row; // Overwrite previous
     
}
      unset(
$last); // Break the reference
   
}
    else return
NULL;
   
   
// Done
   
return $out;
}

// A sample result set to test the function with
$data = Array(Array('name' => 'row 1', 'foo' => 'foo_a', 'bar' => 'bar_a', 'baz' => 'baz_a'),
              Array(
'name' => 'row 2', 'foo' => 'foo_a', 'bar' => 'bar_a', 'baz' => 'baz_b'),
              Array(
'name' => 'row 3', 'foo' => 'foo_a', 'bar' => 'bar_b', 'baz' => 'baz_c'),
              Array(
'name' => 'row 4', 'foo' => 'foo_b', 'bar' => 'bar_c', 'baz' => 'baz_d')
              );

// First, let's key it by one column (result: two-dimensional array)
print_r(array_key_by($data, 'baz'));

// Or, key it by two columns (result: 3-dimensional array)
print_r(array_key_by($data, Array('baz', 'bar')));

// We could also key it by three columns (result: 4-dimensional array)
print_r(array_key_by($data, Array('baz', 'bar', 'foo')));

?>
dnhuff at acm dot org
09-Jun-2008 06:33
In reply to Drewseph using foo($a = 'set'); where $a is a reference formal parameter.

$a = 'set' is an expression. Expressions cannot be passed by reference, don't you just hate that, I do. If you turn on error reporting for E_NOTICE, you will be told about it.

Resolution: $a = 'set'; foo($a); this does what you want.
Drewseph
29-May-2008 11:15
If you set a variable before passing it to a function that takes a variable as a reference, it is much harder (if not impossible) to edit the variable within the function.

Example:
<?php
function foo(&$bar) {
   
$bar = "hello\n";
}

foo($unset);
echo(
$unset);
foo($set = "set\n");
echo(
$set);

?>

Output:
hello
set

It baffles me, but there you have it.
Amaroq
01-Apr-2008 06:56
The order in which you reference your variables matters.

<?php
$a1
= "One";
$a2 = "Two";
$b1 = "Three";
$b2 = "Four";

$b1 =& $a1;
$a2 =& $b2;

echo
$a1; //Echoes "One"
echo $b1; //Echoes "One"

echo $a2; //Echoes "Four"
echo $b2; //Echoes "Four"
?>
charles at org oo dot com
19-Oct-2007 10:59
points to post below me.
When you're doing the references with loops, you need to unset($var).

for example
<?php
foreach($var as &$value)
{
...
}
unset(
$value);
?>
Hlavac
09-Oct-2007 09:25
Watch out for this:

foreach ($somearray as &$i) {
  // update some $i...
}
...
foreach ($somearray as $i) {
  // last element of $somearray is mysteriously overwritten!
}

Problem is $i contians reference to last element of $somearray after the first foreach, and the second foreach happily assigns to it!
dovbysh at gmail dot com
06-Jul-2007 07:50
Solution to post "php at hood dot id dot au 04-Mar-2007 10:56":

<?php
$a1
= array('a'=>'a');
$a2 = array('a'=>'b');

foreach (
$a1 as $k=>&$v)
$v = 'x';

echo
$a1['a']; // will echo x

unset($GLOBALS['v']);

foreach (
$a2 as $k=>$v)
{}

echo
$a1['a']; // will echo x

?>
amp at gmx dot info
08-Jun-2007 05:59
Something that might not be obvious on the first look:
If you want to cycle through an array with references, you must not use a simple value assigning foreach control structure. You have to use an extended key-value assigning foreach or a for control structure.

A simple value assigning foreach control structure produces a copy of an object or value. The following code

$v1=0;
$arrV=array(&$v1,&$v1);
foreach ($arrV as $v)
{
  $v1++;
  echo $v."\n";
}

yields

0
1

which means $v in foreach is not a reference to $v1 but a copy of the object the actual element in the array was referencing to.

The codes

$v1=0;
$arrV=array(&$v1,&$v1);
foreach ($arrV as $k=>$v)
{
    $v1++;
    echo $arrV[$k]."\n";
}

and

$v1=0;
$arrV=array(&$v1,&$v1);
$c=count($arrV);
for ($i=0; $i<$c;$i++)
{
    $v1++;
    echo $arrV[$i]."\n";
}

both yield

1
2

and therefor cycle through the original objects (both $v1), which is, in terms of our aim, what we have been looking for.

(tested with php 4.1.3)
firespade at gmail dot com
03-Apr-2007 02:11
Here's a good little example of referencing. It was the best way for me to understand, hopefully it can help others.

$b = 2;
$a =& $b;
$c = $a;
echo $c;

// Then... $c = 2
php at hood dot id dot au
05-Mar-2007 06:56
I discovered something today using references in a foreach

<?php
$a1
= array('a'=>'a');
$a2 = array('a'=>'b');

foreach (
$a1 as $k=>&$v)
$v = 'x';

echo
$a1['a']; // will echo x

foreach ($a2 as $k=>$v)
{}

echo
$a1['a']; // will echo b (!)
?>

After reading the manual this looks like it is meant to happen. But it confused me for a few days!

(The solution I used was to turn the second foreach into a reference too)
ladoo at gmx dot at
17-Apr-2005 09:05
I ran into something when using an expanded version of the example of pbaltz at NO_SPAM dot cs dot NO_SPAM dot wisc dot edu below.
This could be somewhat confusing although it is perfectly clear if you have read the manual carfully. It makes the fact that references always point to the content of a variable perfectly clear (at least to me).

<?php
$a
= 1;
$c = 2;
$b =& $a; // $b points to 1
$a =& $c; // $a points now to 2, but $b still to 1;
echo $a, " ", $b;
// Output: 2 1
?>
php.devel at homelinkcs dot com
15-Nov-2004 11:16
In reply to lars at riisgaardribe dot dk,

When a variable is copied, a reference is used internally until the copy is modified.  Therefore you shouldn't use references at all in your situation as it doesn't save any memory usage and increases the chance of logic bugs, as you discoved.
joachim at lous dot org
10-Apr-2003 10:46
So to make a by-reference setter function, you need to specify reference semantics _both_ in the parameter list _and_ the assignment, like this:

class foo{
   var $bar;
   function setBar(&$newBar){
      $this->bar =& newBar;
   }
}

Forget any of the two '&'s, and $foo->bar will end up being a copy after the call to setBar.

 
show source | credits | stats | sitemap | contact | advertising | mirror sites