switch文やループの操作をする際に使用される制御構造に、continueとbreakが あります。

大概の入門書で登場し、動作自体は非常に単純なものなので、意外とこれらのマ ニュアルを省みない人も多いのではないでしょうか。

しかしマニュアルをよく見ると、ちょっと便利な動作をしてくれることがわかり ます。

ご存知のとおり、continueはループ内の残り処理をスキップして条件式判定まで 戻り、breakはループ処理を終了します。

動作の違いはありますが、いずれも現在のループを抜ける制御構造です。

しかし、これらは単に現在のループを抜けるだけでなく、以下のように指定する ことで現在のループとその上のレベルのループの、2重ループを抜けることが可 能です。

$count = 0;
echo "start\n";
while (true) {
    $count++;
    echo "one : $count\n";
    while (true) {
        echo "two\n";
        if ($count < 3) {
            continue 2;
        } else {
            break 2;
        }
    }
}
echo "end\n";

結果:=======================

start
one : 1
two
one : 2
two
one : 3
two
end

ここでは例として2重ループのcontinue/breakを行いましたが、2重ループに限ら ず、それぞれの引数として処理をスキップ/中断するループのレベルを指定する ことができます。(例えば、break 3; とすれば3重ループをbreakします。) これを使いこなすとループ操作が非常に楽になり、便利です。

さて、これだけだと「PHPのマニュアルは有益だからよく読みましょう」だけで 終わってしまいますので、このネタの続きをもう少し。

PHPの各種言語構造や関数は、他の言語に比べて柔軟な動作をします。(人によっ ては、柔軟とは呼ばないかもしれませんが・・・。)

よく言われるところでは、switch...case構文でcaseの値に関数や条件式を指定 できる点などがあります。

今回のテーマであるcontinue/breakのループレベル指定も、その例に漏れずなか なか柔軟です。

まず、この引数(ループレベル指定)に0や-1といった、そもそもループのレベル として存在し得ない整数値を与えた場合には、何も指定しなかった時と同様に現 在のループのみを抜ける動作になります。(なお、Noticeは出ません。)

for ($i = 0; $i < 3; $i++) {
    for ($j = 0; $j < 3; $j++) {
        echo "$i : $j  \n";
            continue -2;
    }
}

結果:==========================

0 : 0
0 : 1
0 : 2
1 : 0
1 : 1
1 : 2
2 : 0
2 : 1
2 : 2

また、引数に対してint型以外の値や変数、もしくは演算式や関数などを与える と、きちんとint型に型変換して評価してくれます。

演算式や関数の場合は、その返り値に対して同様の評価が行われます。 このため、単純な例ですが、以下のような事も可能です。

$count = 0;

while (true) {
    echo "start\n";
    while (true) {
        echo "one\n";
        while (true) {
            echo "two\n";
            while (true) {
                echo "three\n";
                while (true) {
                    echo "four : $count\n";
                    break $count++;
                }
            }
        }
    }
}
echo"end : count = $count \n";

結果:=======================

start
one
two
three
four : 0
three
four : 1
three
four : 2
two
three
four : 3
one
two
three
four : 4
start
one
two
three
four : 5
end : count = 6

実際に例のような深いネスト構造がスクリプト中に現れるのは、あまり良い事で はありません。

ですが、breakの引数にユーザー定義関数を配置することも可能であることを考 えれば、使い方次第で色々できる気がしてきませんか?

このような柔軟性を、PHPの良いところと見るか悪いところと見るかは、使う人 次第でしょう。

しかし、こういう処理が可能なことを知っておくのも、何かの足しになるかもし れませんね。


(アシアル 亀本大地)


この記事は、アシアルが運営するPHP開発者のためのポータル&コミュニティサイト「PHPプロ!」で毎週配信しているPHP・TIPSメーリングリストを再録したものです。
同サイトでは、他にもPHP最新ニュースや、困ったときのQ&A掲示板、初心者向けのPHP講座など、PHP開発者をサポートする情報を掲載しています。