Petit problème PHP :)

Trouvez la solution à ce petit problème :

Ce bout de code :

<?php
$arr = array('A', 'B', 'C');
foreach ($arr as &$val) {}
foreach ($arr as $val) {}
var_dump($arr);
?>

Affiche :

array(3) {
     [0]=>  string(1) "A"
     [1]=>  string(1) "B"
     [2]=>  &string(1) "B"
}

Oui ! A, B, B !

POURQUOI ?

En fait, après le premier foreach, $val n'est qu'une variable par référence qui pointe sur la dernière entrée du tableau, ce qui veux dire que peux importe ce qui lui sera assigné, la modification remplacera le C. Cela explique la perte du C, mais pourquoi B ?

C'est très logique.

  • Dans le deuxième foreach, à la première itération, on attribue A (premier élément) à &$var, qui modifie donc array (A, B, C) en array (A, B, A).
  • Lors de la deuxième itération, on attribue B à &$var, donc a la dernière entrée du tableau. Ce qui fait que nous passons de array (A, B, A) à array (A, B, B).
  • Et c'est maintenant que la solution apparaît, lors de la troisième et dernière itération, foreach va lire le dernier élément du tableau, qui est ? B ! Et oui, il à été mis à jour lors de la précédente itération (array (A, B, B)). Il va donc assimiler la valeur B à &$var, donc à la dernière entrée du tableau, B.

Voilà ! Un peu étrange, mais pourtant logique.

Voici le output d'un var_dump à chaque itérations dans le second foreach :

<?
// Tableau d'origine
array(3) {
  [0]=>
  string(1) "A"
  [1]=>
  string(1) "B"
  [2]=>
  string(1) "C"
}

// Suite à la première itération, on assimile A à &$var
array(3) {
  [0]=>
  string(1) "A"
  [1]=>
  string(1) "B"
  [2]=>
  &string(1) "A"
}

// Suite à la seconde, on assimile B à &$var
array(3) {
  [0]=>
  string(1) "A"
  [1]=>
  string(1) "B"
  [2]=>
  &string(1) "B"
}

// Troisième et dernière itération, on assimile la dernière valeur du tableau
// Qui à été mise à jour juste avant par B, à &$var
array(3) {
  [0]=>
  string(1) "A"
  [1]=>
  string(1) "B"
  [2]=>
  &string(1) "B"
}

// Ce qui nous donne bien :
array(3) {
  [0]=>
  string(1) "A"
  [1]=>
  string(1) "B"
  [2]=>
  &string(1) "B"
}
?>

Posted by Cyril Nicodème