【2019年11月15日】

配列の全ての要素を順番に参照して処理を行うforeach文。
構文的には、

<?php

foreach ($array as $val) {
    echo $val;
}

?>

という感じなのはご存知の通り。
このforeach、上記の例で言うと内部的には$arrayの各要素をループの都度、$valという変数に入れてその変数をforeachの括りの中で使用するような形になる。
つまり、$valというのは$arrayの要素を直接参照しているものではないである。

で、それがどうしたのかというと、この$valにforeachの括りの中で何かを代入しても、基となる$arrayの要素は書き換わらないということ。

たとえば、

<?php

$array = array(1, 2, 3);
foreach ($array as $val) {
    $val = $val * 2;
}
var_dump($array);

?>
array(3) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  int(3)
}

数値を格納した配列に対してforeachで全ての要素を2倍してみた。
その後、配列の中身を見てみると、変化していない。

こういう場合にちゃんと書き換わってほしい場合、いくつか方法がある。
まず、forで代用する方法。

<?php

$array = array(1, 2, 3);
for ($i = 0; $i < count($array); $i) {
    $array[$i] = $array[$i] * 2;
}
var_dump($array);

?>
array(3) {
  [0]=>
  int(2)
  [1]=>
  int(4)
  [2]=>
  int(6)
}

次に、foreachで、キーを使用する方法。

<?php

$array = array(1, 2, 3);
foreach ($array as $key => $val) {
    $array[$key] = $val * 2;
}
var_dump($array);

?>
array(3) {
  [0]=>
  int(2)
  [1]=>
  int(4)
  [2]=>
  int(6)
}

もう一つは、foreachの内部変数を参照型にする方法。
この方法だと$valに&を付けるだけ。

ちなみにこれはPHP5でしか効かない。
PHP4だと&をつけても無駄のようである。

<?php

$array = array(1, 2, 3);
foreach ($array as &$val) {
    $val = $val * 2;
}
var_dump($array);

?>
array(3) {
  [0]=>
  int(2)
  [1]=>
  int(4)
  [2]=>
  int(6)
}

いずれか、好みで使い分ければよい。