[PHP]do…whileとは?最低1回は必ず実行される後判定ループを徹底解説

PHP

はじめに

前回の記事では、条件が true の間繰り返す「前判定ループ」である while を解説しました。今回取り上げる do...while は、その兄弟とも言える構文ですが、条件を評価するタイミングが決定的に異なります。

do...while は、まず処理ブロックを1回実行してから、条件式を評価する「後判定ループ」です。この違いにより、「条件の真偽に関わらず、少なくとも1回はこの処理を実行したい」という要件を自然に表現できます。ユーザー入力の検証ループ、リトライ処理、メニュー選択ループなど、「まず1回試してから、必要に応じて繰り返す」という場面で特に活躍します。本記事では基本的な使い方から、while との使い分け、実践的な活用例まで詳しく解説します。


構文概要

項目内容
構文名do...while
種別制御構造(ループ構文)
基本構文do { 処理 } while (条件式);
評価タイミングループの末尾で条件式を評価する(後判定ループ)
最低実行回数条件の真偽に関わらず必ず1回は処理が実行される
文末のセミコロンwhile (条件式) の後にセミコロン;が必須
対応バージョンPHP 4以前から存在する最古参の構文の一つ

whileとの決定的な違い(イメージ図)

  【while - 前判定】
  while (false) {
      echo 'この処理は一度も実行されない';
  }
              │
              ▼
  何も出力されない(条件が最初からfalseのため)


  【do...while - 後判定】
  do {
      echo 'この処理は必ず1回実行される';
  } while (false);
  ★この記事の対象
              │
              ▼
  "この処理は必ず1回実行される" が出力される
  (条件の評価は処理の"後"に行われるため)

ポイントは、do...while がブロックの中身を実行してから、初めて条件式を評価するという点です。これにより、条件がどうであれ「最初の1回」が保証されるという、while にはない特性を持っています。


実践サンプル7選

例1:基本的な使い方

<?php

$count = 0;

do {
    echo "カウント: {$count}" . PHP_EOL;
    $count++;
} while ($count < 5);

例2:条件が最初からfalseでも1回は実行されることを確認する

<?php

$condition = false;

// whileなら一度も実行されないが、do-whileでは必ず1回実行される
do {
    echo 'このメッセージは必ず表示されます' . PHP_EOL;
} while ($condition);

例3:ユーザー入力の検証ループ(CLIアプリケーションでの典型例)

<?php

function simulateUserInput(array $inputs): void
{
    $index = 0;
    $isValid = false;

    /**
     * 「まず1回入力を受け付けてから、妥当性をチェックする」という
     * 流れを自然に表現できる、do-whileの典型的な活用パターン
     */
    do {
        $input = $inputs[$index] ?? '';
        $index++;

        echo "入力値: '{$input}' を検証中..." . PHP_EOL;
        $isValid = !empty($input) && is_numeric($input);

        if (!$isValid) {
            echo '無効な入力です。再試行します。' . PHP_EOL;
        }
    } while (!$isValid && $index < count($inputs));

    echo $isValid ? '検証成功' : '検証失敗(試行回数超過)';
    echo PHP_EOL;
}

simulateUserInput(['abc', '', '123']);

例4:リトライ処理での活用

<?php

class ApiCaller
{
    /**
     * 「最低1回はAPIを呼び出す」ことが前提の処理には
     * do-whileが自然にフィットする
     */
    public function callWithRetry(callable $apiCall, int $maxAttempts = 3): bool
    {
        $attempt = 0;
        $success = false;

        do {
            $attempt++;
            echo "APIコール試行 {$attempt}回目" . PHP_EOL;

            try {
                $apiCall();
                $success = true;
            } catch (\Throwable $e) {
                echo "失敗: {$e->getMessage()}" . PHP_EOL;
            }
        } while (!$success && $attempt < $maxAttempts);

        return $success;
    }
}

$caller = new ApiCaller();
$tryCount = 0;
$caller->callWithRetry(function () use (&$tryCount) {
    $tryCount++;
    if ($tryCount < 2) {
        throw new \RuntimeException('接続エラー');
    }
    echo '成功しました' . PHP_EOL;
});

例5:breakを使った早期終了との組み合わせ

<?php

$items = ['A', 'B', 'STOP', 'C'];
$index = 0;

do {
    $current = $items[$index];

    if ($current === 'STOP') {
        echo '停止シグナルを検出しました' . PHP_EOL;
        break; // do-while内でもbreakは通常通り使える
    }

    echo "処理中: {$current}" . PHP_EOL;
    $index++;
} while ($index < count($items));

例6:セミコロンの付け忘れによる構文エラーの確認

<?php

$x = 0;

// 正しい書き方: whileの後に必ずセミコロンが必要
do {
    $x++;
} while ($x < 3);

echo "x = {$x}" . PHP_EOL;

// 誤った書き方(コメントアウト):
// do {
//     $x++;
// } while ($x < 3)   ← セミコロンがないと構文エラーになる

例7:メニュー選択をシミュレートするループ構造

<?php

class MenuSimulator
{
    private array $choices = ['view', 'edit', 'exit'];
    private int $step = 0;

    /**
     * 対話的なメニューは「まず選択肢を表示してから、
     * 終了が選ばれるまで繰り返す」という性質上、
     * do-whileと非常に相性が良い
     */
    public function run(): void
    {
        do {
            $choice = $this->choices[$this->step] ?? 'exit';
            echo "選択: {$choice}" . PHP_EOL;
            $this->step++;
        } while ($choice !== 'exit' && $this->step < count($this->choices));

        echo 'メニューを終了します' . PHP_EOL;
    }
}

(new MenuSimulator())->run();

関連機能との比較

機能役割do…whileとの違い
do...while条件がtrueの間、処理を繰り返す(後判定)本記事の対象。必ず最低1回は処理が実行される
while条件がtrueの間、処理を繰り返す(前判定)ループ本体の実行前に条件を評価するため、0回実行の可能性がある(前回記事を参照)
for初期化・条件・更新式を1行にまとめた繰り返し繰り返し回数があらかじめ決まっている場合に適する
foreach配列やイテレータの要素を順に処理する配列の走査に特化しており、条件判定のループとは目的が異なる
break / continueループの制御(中断・スキップ)do...while自体ではなく、ループ内部での流れを制御する補助的な構文

よくある落とし穴(注意点)

  1. while (条件);の後のセミコロンを忘れると構文エラーになる do { ... } while (条件式) の末尾には、必ずセミコロン ; が必要です。通常の while ループにはこのセミコロンはないため、混同して書き忘れがちな点です(例6を参照)。
  2. 「最低1回実行される」という特性を忘れて不適切な場面で使ってしまう 条件が最初から明らかに false である可能性がある処理(例えば、空の配列に対する処理など)に do-while を安易に使うと、意図せず1回だけ不正な処理が実行されてしまうことがあります。本当に「最低1回の実行」が必要かどうかを見極めて使いましょう。
  3. whileとの使い分けの判断基準を明確にする 「条件を先にチェックしてから処理すべきか」「とにかく1回は処理してから条件をチェックすべきか」という設計上の意図を明確にすることが、while と do-while の適切な選択につながります。多くの場合、PHPでは while の方が使用頻度が高く、do-while は限定的な場面(リトライ処理やメニューループなど)で使われます。
  4. 無限ループのリスクはwhileと同様に存在する do-while もループである以上、終了条件に関わる変数の更新を忘れると無限ループに陥ります。while と同じ注意が必要です。
  5. 代替構文(コロン構文)は存在しない if や while、for、foreach にはHTMLテンプレート向けのコロン構文(endif;、endwhile; など)が用意されていますが、do-while にはこうした代替構文がありません。テンプレート内で使う場合は、通常の中括弧構文のまま記述する必要があります。

まとめ

観点まとめ
何をする構文か処理ブロックを実行してから条件式を評価し、trueであれば繰り返す(後判定ループ)
主な用途ユーザー入力の検証ループ、リトライ処理、メニュー選択ループ
whileとの違い条件に関わらず、必ず最低1回は処理が実行される
構文上の注意点while (条件式)の後に必ずセミコロンが必要
注意点無限ループのリスク、不適切な場面での使用、代替構文(コロン構文)が存在しないこと

do...while は、「まず1回試してから、必要であれば繰り返す」という、while とは異なるニュアンスの処理を自然に表現できる、PHPの基本的なループ構文です。使用頻度こそ while や for ほど高くありませんが、リトライ処理やメニューループのような「最低1回の実行」が前提となる場面では、コードの意図を明確に伝えるための良い選択肢になります。

タイトルとURLをコピーしました