はじめに
前回の記事では、条件が 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自体ではなく、ループ内部での流れを制御する補助的な構文 |
よくある落とし穴(注意点)
while (条件);の後のセミコロンを忘れると構文エラーになるdo { ... } while (条件式)の末尾には、必ずセミコロン;が必要です。通常のwhileループにはこのセミコロンはないため、混同して書き忘れがちな点です(例6を参照)。- 「最低1回実行される」という特性を忘れて不適切な場面で使ってしまう 条件が最初から明らかに
falseである可能性がある処理(例えば、空の配列に対する処理など)にdo-whileを安易に使うと、意図せず1回だけ不正な処理が実行されてしまうことがあります。本当に「最低1回の実行」が必要かどうかを見極めて使いましょう。 whileとの使い分けの判断基準を明確にする 「条件を先にチェックしてから処理すべきか」「とにかく1回は処理してから条件をチェックすべきか」という設計上の意図を明確にすることが、whileとdo-whileの適切な選択につながります。多くの場合、PHPではwhileの方が使用頻度が高く、do-whileは限定的な場面(リトライ処理やメニューループなど)で使われます。- 無限ループのリスクは
whileと同様に存在するdo-whileもループである以上、終了条件に関わる変数の更新を忘れると無限ループに陥ります。whileと同じ注意が必要です。 - 代替構文(コロン構文)は存在しない
ifやwhile、for、foreachにはHTMLテンプレート向けのコロン構文(endif;、endwhile;など)が用意されていますが、do-whileにはこうした代替構文がありません。テンプレート内で使う場合は、通常の中括弧構文のまま記述する必要があります。
まとめ
| 観点 | まとめ |
|---|---|
| 何をする構文か | 処理ブロックを実行してから条件式を評価し、trueであれば繰り返す(後判定ループ) |
| 主な用途 | ユーザー入力の検証ループ、リトライ処理、メニュー選択ループ |
whileとの違い | 条件に関わらず、必ず最低1回は処理が実行される |
| 構文上の注意点 | while (条件式)の後に必ずセミコロンが必要 |
| 注意点 | 無限ループのリスク、不適切な場面での使用、代替構文(コロン構文)が存在しないこと |
do...while は、「まず1回試してから、必要であれば繰り返す」という、while とは異なるニュアンスの処理を自然に表現できる、PHPの基本的なループ構文です。使用頻度こそ while や for ほど高くありませんが、リトライ処理やメニューループのような「最低1回の実行」が前提となる場面では、コードの意図を明確に伝えるための良い選択肢になります。
