この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:8
ページ更新者:爽健
更新日時:2026-06-11 07:07:02

タイトル: 繰り返し処理
SEOタイトル: PHP 繰り返し処理完全ガイド (for/foreach/while/array_map)

この記事の要点
  • PHP の基本ループ 4 種: for / foreach / while / do-while
  • 配列処理は foreach ($arr as $value) または foreach ($arr as $key => $value) が定番
  • 関数型: array_map / array_filter / array_walk / array_reduce
  • generators (yield) でメモリ効率の良い遅延評価ループ
  • PHP 8+ の match 式は switch 代替。break N で深いネスト脱出

PHP のループ 4 種

foreach 構文の 2 形式

 90, 'Bob' => 80, 'Carol' => 70];

// 形式1: value のみ
foreach ($scores as $score) {
    echo $score, "\n";          // 90, 80, 70
}

// 形式2: key => value
foreach ($scores as $name => $score) {
    echo "$name : $score\n";    // Alice : 90 ...
}

// ★ 参照渡し ($value への代入で配列本体を書き換え)
foreach ($scores as &$score) {
    $score += 10;
}
unset($score);    // ★ 必須: 参照を解除しないと次のループでバグる

print_r($scores);   // 100, 90, 80

foreach の参照渡しの罠

break / continue / 多重ループ

関数型: array_map / array_filter / array_reduce

 $n * 2, $nums);
// → [2, 4, 6, 8, 10]

// array_filter : 条件で抜き出す
$even = array_filter($nums, fn($n) => $n % 2 === 0);
// → [1 => 2, 3 => 4]  ★ キーが保持される (再番号化したいなら array_values)

// array_reduce : 集約
$sum = array_reduce($nums, fn($acc, $n) => $acc + $n, 0);
// → 15

// array_walk : 参照渡しで全要素を変更 (戻り値は bool)
array_walk($nums, function (&$v, $k) { $v *= 10; });
// → $nums = [10, 20, 30, 40, 50]

// 連鎖: filter → map → reduce
$total = array_reduce(
    array_map(fn($n) => $n * 2,
        array_filter($nums, fn($n) => $n > 2)
    ),
    fn($acc, $n) => $acc + $n,
    0
);   // (3+4+5)*2 = 24

Generators (yield) — 遅延評価ループ

巨大データを全部メモリに乗せたくないとき、yield で 1 件ずつ生成する Generator が便利です。

 value 生成
function user_iter(): Generator {
    yield 'alice' => 90;
    yield 'bob'   => 80;
}
foreach (user_iter() as $name => $score) { ... }

PHP 8 の match 式

 '進行中',
    3       => '完了',
    default => '?',
};

// 条件式も書ける
$grade = match (true) {
    $score >= 90 => 'A',
    $score >= 70 => 'B',
    $score >= 50 => 'C',
    default      => 'F',
};

無限ループ防止

= $max) {
    throw new RuntimeException('Loop guard exceeded');
}

// PHP 設定でも防御
// php.ini : max_execution_time = 30  → 30 秒で fatal

性能比較 (10 万件処理の例)

方式速度メモリ用途
foreach (値)★★★ 最速定番
foreach (参照 &)★★★要素書き換え
for + $arr[$i]★★ やや遅index 必須
array_map★★ 関数呼び出しコスト中 (新配列)不変な変換
Generator (yield)★ やや遅★ 極小巨大データ

使い分けチートシート

  • 配列を順に処理 → foreach
  • index が必要、または個数ベースで回す → for
  • 終了条件が動的・読み込みが続く間 → while
  • 必ず 1 回は実行 (リトライ等) → do-while
  • 配列を変換して新配列にしたい → array_map
  • 絞り込みたい → array_filter
  • 合計・最大等の集約 → array_reduce
  • メモリ節約したい巨大データ → Generator (yield)

FAQ

Q: foreach のキー $key はインデックスとは限らない?
A: 連想配列なら文字列キー、添字配列なら 0 始まり整数。array_values() で再番号化可能。

Q: foreach で要素削除したい
A: foreach 内で unset($arr[$key]) は可。ただし参照渡しと併用すると挙動が複雑array_filter で別配列にする方が安全。

Q: 関数型 (array_map 等) と foreach、どちらを使う?
A: 不変な変換は array_map、副作用 (DB 保存等) を含むなら foreach。Closure オーバーヘッドで foreach のほうが若干速い。