PHPで配列の各要素を順番に処理するなら foreach が最適です。基本はシンプルですが、参照渡し(&)で要素を変更したあとにunset() を忘れると、最後の要素が壊れるという有名な落とし穴があります。この記事では基本から、その注意点まで実例で解説します。
この記事の結論:
foreach ($arr as $value) で値を、foreach ($arr as $key => $value) でキーと値を取得します。要素を直接書き換えるなら foreach ($arr as &$value)(参照渡し)ですが、ループ後に必ず unset($value) してください。基本的な使い方
値を順番に取り出す
<?php
$fruits = ["apple", "banana", "cherry"];
foreach ($fruits as $fruit) {
echo $fruit . "\n";
}
// apple / banana / cherry
キーと値を同時に取得する
連想配列では $key => $value でキーと値の両方を取得できます。
キーと値
<?php
$person = ["name" => "John", "age" => 30, "city" => "NY"];
foreach ($person as $key => $value) {
echo "$key: $value\n";
}
// name: John / age: 30 / city: NY
通常のforeachは「コピー」を操作する
通常の foreach ($arr as $value) では、$value は各要素のコピーです。これを変更しても元の配列は変わりません。
コピーなので元配列は変わらない
<?php
$numbers = [1, 2, 3];
foreach ($numbers as $n) {
$n *= 2; // コピーを変更しているだけ
}
print_r($numbers); // [1, 2, 3](変わらない)
参照渡し(&)で要素を直接変更する
元の配列を直接書き換えたいときは、&$value と参照渡しにします。
参照渡しで2倍にする
<?php
$numbers = [1, 2, 3];
foreach ($numbers as &$n) {
$n *= 2;
}
unset($n); // ★ ループ後に必ず参照を解除
print_r($numbers); // [2, 4, 6]
要注意:unsetを忘れると最後の要素が壊れる
参照渡しの &$value は、ループ後も最後の要素を指したままです。ここで unset() を忘れて別の foreach を回すと、同じ変数名が最後の要素を上書きしてしまい、データが壊れます。
NG: unset忘れによる有名なバグ
<?php
$a = [1, 2, 3];
foreach ($a as &$v) { $v *= 2; } // [2, 4, 6]、$v は最後の要素を参照したまま
// unset($v); を忘れた!
foreach ($a as $v) { /* 何もしない */ }
// 2回目のループで $v に各値が代入され、参照先(最後の要素)が上書きされる
print_r($a); // [2, 4, 4] ← 最後が 6 ではなく 4 に壊れる!
参照渡しの
foreach の直後は必ず unset($v) しましょう。これを忘れると、後続の処理で最後の要素が書き換わる、再現しにくいバグになります。参照が不要なら、そもそも array_map() で新しい配列を作る方が安全な場合もあります。途中で抜ける・スキップする(break / continue)
条件でループを抜けるなら break、その回だけ飛ばすなら continue を使います。
break / continue
<?php
$nums = [1, 2, 3, 4, 5];
foreach ($nums as $n) {
if ($n === 4) break; // 4で終了
if ($n % 2 === 0) continue; // 偶数は飛ばす
echo $n . "\n"; // 1 / 3
}
応用:要素を分割代入する
各要素が配列のとき、foreach 内で分割代入すると見やすくなります。
list()短縮構文で分割代入
<?php
$points = [[1, 2], [3, 4], [5, 6]];
foreach ($points as [$x, $y]) {
echo "($x, $y)\n";
}
// (1, 2) / (3, 4) / (5, 6)
よくある質問(FAQ)
Qforeachで元の配列を変更できますか?
A通常の
foreach ($arr as $value) はコピーなので元配列は変わりません。直接変更するには foreach ($arr as &$value) と参照渡しにし、ループ後に unset($value) を忘れずに行ってください。Qunsetを忘れるとどうなりますか?
A参照変数が最後の要素を指したまま残り、後続の
foreach で最後の要素が上書きされて壊れます(例: [2,4,6] が [2,4,4] に)。参照渡しの直後は必ず unset() してください。Qキーも一緒に取得するには?
A
foreach ($arr as $key => $value) と書きます。連番配列ではキーが 0, 1, 2…、連想配列では設定したキーが得られます。Q途中で抜ける・特定の要素を飛ばすには?
Aループを抜けるなら
break、その回だけ飛ばすなら continue を使います。まとめ
PHPのforeachのポイントを整理します。
- 値は
foreach ($arr as $v)、キーと値は$k => $v - 通常はコピー。元配列を変えるなら 参照渡し
&$v - 参照渡しの直後は必ず
unset($v)(忘れると最後の要素が壊れる) - 抜けるなら
break、飛ばすならcontinue - 要素が配列なら
foreach ($arr as [$a, $b])で分割代入
関連として、foreachをbreakで終了する方法・continueでスキップする方法・ループ処理を行う方法もあわせて読むと、PHPのループ処理に強くなれます。

