制御構造

今までのサンプルのスクリプトでは、「何かを出力する」とか「変数に値を代入する」という事をしてきました。これらは、PHPという言語の言語構造、要するにPHPの機能なわけですが、PHPには勿論他にも色んな機能があるわけで。今までは実行する処理をただ上から順に「あーしろこーしろ」と書き連ねただけの形でしたが、これだけではわざわざPHPを使わなくても、HTMLのみで実現可能です。で、今まで書いたスクリプトの構造を、「連接構造」と言います。ただ単に実行したい処理を上から書き連ねていっただけという構造です。これに、「選択構造」と「反復構造」を追加して組み合わせる事で、HTMLだけでは実現不可能な処理を記述する事が出来るわけです。「連接構造」、「選択構造」、「反復構造」の3つを、「プログラムの基本三構造」と言います。

選択構造

選択構造とは如何なるものか?選択構造とは、条件によって処理を行うか行わないかを振り分ける構造をいい、この選択構造を実現するのが、「if文」、「else文」、「elseif文」、「switch文」です。

if文

次のサンプルをご覧下さい。

<html>
<body>
<?php
    $hode = true;
    if($hode){
        echo "HODENASU";
    }
    
    echo "<hr />";
    
    $hode = false;
    if($hode){
        echo "HODENASU";
    }
?>
</body>
</html>

結果は以下の通り。

HODENASU

今回のサンプルには、また新しく色んなものが登場しています。まず、「変数$hode」に代入した「true」と「false」です。一見、文字列のようにも見えますが、二重引用符「"(ダブルクォーテーション)」で囲んでありません。これらは、「真偽値」と呼ばれるもので、「true」が「」、「false」が「」であるという特別な意味を持っています。で、「」とか「」とは一体何なのかですが、それぞれ言い換えると、「」が「そうですよ」で「」が「そうではありませんよ」と言う意味です。

次に登場したのが、「if($hode){ 処理 }」の部分。「if」、「($hode)」、「{ 処理 }」というパーツで構成されています。これは、『もし、「$hode」の値が「」なら、「{ 処理 }」を実行する』という「if文」という選択構造であり、この構造に適合させて書いた「選択文」です。そして、この選択文の中の、「if」の後に来る「丸括弧」の中の「$hode」を、「条件式」と言います(「式」とは、「値を持ったもの」の事をいいます)。

今回のサンプルの結果を見ると、1つめの「if文」は「条件式」の値が「」だったので「{ 処理 }」が実行され、2つめは、「条件式」の値が「」だったので「{ 処理 }」は実行されていません。

else文

先程の「if文」は、「条件式」の値が「」なら「{ 処理 }」を実行するというものでした。今回の「else文」は、「if文」と組み合わせて使い、「if文」の「条件式」の値が「」の場合に実行する処理(文)を記述します。

<html>
<body>
<?php
    $hode = true;
    if($hode){
        echo "NDEGASU";
    }else{
        echo "NDENEGASU";
    }
    
    echo "<hr />";
    
    $hode = false;
    if($hode){
        echo "NDEGASU";
    }else{
        echo "NDENEGASU";
    }
?>
</body>
</html>

結果は以下の通り。

NDEGASU

NDENEGASU

1つめの選択文では、「if文」の「条件式」の値が「」なので「NDEGASU」が出力され、2つめでは、「if文」の「条件式」の値が「」なので「NDENEGASU」が出力されています。

elseif文

先程の「else文」は、「if文」の「条件式」の値が「」なら「{ 処理 }」を実行するというものでしたが、更に「else」の後ろに「if(条件式)」を付ける事ができます。

<html>
<body>
<?php
    $hode = true;
    $nasu = false;
    if($hode){
        echo "NDEGASU";
    }elseif($nasu){
        echo "NDENEGASU";
    }
    
    echo "<hr />";
    
    if($nasu){
        echo "NDEGASU";
    }elseif($hode){
        echo "NDENEGASU";
    }
?>
</body>
</html>

結果は以下の通り。

NDEGASU

NDENEGASU

1つめの選択文では、「if文」の「条件式」の値が「」なので「NDEGASU」が出力され、2つめでは、「if文」の「条件式」の値が「」で、「else」の後ろの「if文」の「条件式」の値が「」なので「NDENEGASU」が出力されています。なお、「elseif」の部分は、「else if」のように、「else」と「if」の間に半角スペースやタブがあっても同じように機能します。

switch文

選択構造のラストは「switch文」です。この構造は、名前の通りスイッチをオンにしたりオフにしたりするイメージの構造をしています。

<html>
<body>
<?php
    $hode = 1;
    $nasu = "b";
    $nda  = 2;
    
    switch($hode){
        default :
            echo "===";
            break;
        case "a":
            echo "=A=";
            break;
        case "b":
            echo "=B=";
            break;
        case "c":
            echo "=C=";
            break;
    }
    
    echo "<hr />";
    
    switch($nasu){
        case "a":
            echo "=A=<br />";
        case "b":
            echo "=B=<br />";
        case "c":
            echo "=C=<br />";
        default :
            echo "===";
    }
    
    echo "<hr />";
    
    switch($nda){
        default :
            echo "=====";
            break;
        case 1:
        case 2:
        case 3:
            echo "=123=";
            break;
        case "a":
        case "b":
        case "c":
            echo "=ABC=";
    }
?>
</body>
</html>

結果は以下の通り。

===

=B= =C= ===
=123=

3つの「switch文」を記述しました。「switch文」は、条件式の値によって、実行する処理を振り分けるという構造です。

1つ目の「switch文」では、条件式の値は「1」です。で、どのように処理を振り分けるのか。「switch($hode){ 処理 }」の中の「処理」の部分。またしても色んなものが登場しています。「default :」や「case "a":」が、「switch文」における、いわゆるスイッチに相当するものです。まず、「case "a":」の方ですが、この中の「"a"」の部分が、条件式の値と一致した場合に、「:(コロン)」の後ろの処理が実行されます。次に、「default :」ですが、こちらは、条件式の値がいずれのケースにも当てはまらなかった場合に実行する処理を書くためのものです。これは、必ずしも書く必要はありません。で、処理の中にある「break;」は、その時点で「switch文」から抜けるという働きを持つものです。サンプルの結果は、いずれのケースにも当てはまらなかったため、「default :」の処理が実行されています。

2つ目の「switch文」では、条件式の値は「"b"」です。「case "b":」の処理のみが実行され、「=B=」のみが出力されると予想されますが、実際にはその後ろに続く処理も全て実行されています。「ホワイ何故に」1つ目と2つ目の「switch文」をよく見比べてみると、前者にあって後者にはないものがあります。「break;」です。これを処理の最後に置かないと、一度スイッチが入ったところから以降全ての処理が実行されてしまいます。そういう処理をさせたいなら別ですが、そうでない場合は処理の最後に「break;」を記述して、「switch文」から抜けます。

3つ目の「switch文」では、条件式の値は「2」です。「case 2:」の処理が実行され・・・と思ったら、「:(コロン)」の後ろに処理の記述がありません。「:(コロン)」の後ろには必ずしも処理の記述がある必要はなく、処理の記述が無い場合は、それ以降「break;」が現れるまでの全ての処理を実行します。サンプルは、条件式の値が「1」か「2」か「3」の何れかなら「=123=」を、「"a"」か「"b"」か「"c"」の何れかなら「=ABC=」を、その他の値なら「=====」を出力するというもので、条件式の値が「2」だったので「=123=」が出力されました。

反復構造

最後の基本三構造、反復構造とは如何なるものか?反復構造とは、条件式の値が「真」の間同じ処理を繰り返す構造をいい、この反復構造を実現するのが、「while文」、「do...while文」、「for文」、「foreach文」です。

while文

まず、次のサンプルをご覧下さい。

<html>
<body>
<?php
    $hode = true;
    while($hode){
        echo "HODENASU";
        echo "<br />";
    }
?>
</body>
</html>

結果は以下の通り。

HODENASU
HODENASU
HODENASU
HODENASU
HODENASU
HODENASU
HODENASU
HODENASU
HODENASU
HODENASU
HODENASU
HODENASU
HODENASU
…(以下、無限に続く・・・。)

大変です。条件式の値が「真」の間中処理を実行する構造のため、サンプルの場合、常に条件式の値は「true」、「真」なので、処理を延々と実行し続ける事になります。最悪、サーバがダウーンしてしまうかも知れません。ちなみに、このように延々と同じ処理を繰り返し実行し続ける悲惨な状態を「無限ループ」と言います。

幸い、PHPには「処理時間が一定時間(デフォルトでは30秒)に達した時点で、エラー発生扱いとして終了する」という機能があるので、ダウンさせる前にミスを発見して修正する事が出来ます。

これまで、条件式の値が「真」なら実行、「偽」なら実行しない。「true」が「真」であり「false」が「偽」であると書き、「switch文」以外の条件式の値は「true」か「false」でしか判定できないのかといった印象があったかと思います。が、実際は、条件式に指定できるものは、『「true」か「false」』では無く、『「真」か「偽」の値』です。『「真」か「偽」の値』のとはどんな値の事なのか?答えは、「値なら何でもかんでも」です。今までのサンプルの中には、文字列、数値、真偽値が登場しました。これら全ての値が『「真」か「偽」の値』に分類出来るのです。まず、文字列の場合、「""」は、空文字列で、「偽」と判定され、それ以外の全てが「真」と判定されます。数値の場合、「0」が「偽」と判定され、それ以外の全てが「真」と判定されます。

以上のことを踏まえた上で、次のサンプルをご覧下さい。

<html>
<body>
<?php
    $hode = 3;
    while($hode){
        echo "HODENASU ";
        echo $hode;
        echo "<br />";
        $hode = $hode - 1;
    }
?>
</body>
</html>

結果は以下の通り。

HODENASU 3
HODENASU 2
HODENASU 1

まず、条件式の値は最初「3」で、ループ内の最後に「1」減算されています。で、条件式の値が「0」になると、反復文は実行されません。パーフェクツ!

do...while文

続きましてー、「do...while文」。まず、次のサンプルをご覧下さい。

<html>
<body>
<?php
    do{
        echo "HODENASU";
    }while(0);
?>
</body>
</html>

結果は以下の通り。

HODENASU

この構造は、「while文」の変形型で、条件判定を処理の後に置いてあります。今回のサンプルでは、条件式が「0」なのでループを全くしないように思われますが、条件判定の前に処理があるため、最低1度は処理が実行されます。注意する点は、「while()」の後ろに「;」を書くのを忘れない事です。

for文

続きましてー、「for文」。「for文」は、最も複雑なループで、理解するのに時間が掛かるかもしれません。ではサンプルを以下に。

<html>
<body>
<?php
    for($i = 1; $i <= 3; $i = $i + 1){
        echo "HODENASU ";
        echo $i;
        echo "<br />";
    }
?>
</body>
</html>

結果は以下の通り。

HODENASU 1
HODENASU 2
HODENASU 3

まず、条件式が大変な事(「($i = 1; $i <= 3; $i = $i + 1)」)になっています。この困ったちゃんな条件式は、「;(セミコロン)」で3つに分ける事が出来ます。「$i = 1」と「$i <= 3」と「$i = $i + 1」の3つに分割してみました。これら3つが何なのか?これら3つを、左から順に「式1」、「式2」、「式3」と呼ぶ事にします。まず、「式1」は『「for文」の中で使うループ条件の判定に使う変数の定義(初期値の設定)』です(オイ)。次に、「式2」は『ループ条件(条件式)』で、この条件式の値が「真」の間、処理を実行し続けます。今回のサンプルでは「$i <= 3」となっていますが、これの意味は、『「変数$i」の値が「3」以下』という意味です。この条件にマッチすれば「真」、マッチしなければ「偽」と判定されます。で最後の「式3」は『ループ条件の判定に使う変数の更新』です。今回のサンプルでは「$i = $i + 1」となっていますが、これは見たまんまの意味ですね。

で、これらの「式1」、「式2」、「式3」が評価(「実行」する事)されるのには順番と言うものがあります。まず最初に「式1」が評価されます。次に「式2」が評価され、条件式の値が「真」なら処理を実行します。処理の実行が終ると、「式3」が評価され、次に「式2」が評価され、条件式の値が「真」なら処理を実行...。という繰り返しを、「式2」の条件式で「偽」と判定されるまでループが続きます。

また、条件式は以下のサンプルのように省略する事も出来ます。

<html>
<body>
<?php
    $i = 1
    for(; $i <= 3; $i = $i + 1){
        echo "HODENASU ";
        echo $i;
        echo "<br />";
    }
?>
</body>
</html>

結果は前回と同じです。また更に、以下のサンプルのように条件式を全て省略する事も可能です。

<html>
<body>
<?php
    for(;;){
        echo "HODENASU!!!";
        break;
    }
?>
</body>
</html>

条件式を全て省略しました。この状態だと、基本的に無限ループになります。後で解説する「break文」によってループから抜け出し、結果的に一度だけループされます。

for文」の条件式は「;(セミコロン)」によって3つの区画に区切られる特殊なものですが、更に、各区画内には、「,(コンマ)」で区切って複数の式を置く事が出来ます。次のサンプルと結果をご覧下さい。

<html>
<body>
<?php
for(print "A<br />", $i = 1; print "B ", $i <= 3;
                             print "C ", $i = $i + 1){
    echo "<br />D(";
    echo $i;
    echo ") ";
}
?>
</body>
</html>
A
B 
D(1) C B 
D(2) C B 
D(3) C B 

条件式内で「print」(「echo」と殆ど同じもの)で文字を出力しています。「for文」の処理の流れがよく解かる結果となりました。

foreach文

反復構造のラストは「foreach文」です。これを理解するには、「配列(「配列」のページで解説)」という特殊な変数を理解している必要があります。また、「オブジェクト(「クラス」のページで解説)」についても理解している必要があります。では、サンプルをご覧下さい。「foreach文」には、2通りの書き方があります。

<html>
<body>
<?php
    $arr = array("HODENASU", "OSYOSUI", "TAMAGERU");
    foreach($arr as $val){
        echo $val;
        echo "<br />";
    }
    
    echo "<hr />";
    
    foreach($arr as $key => $val){
        echo $key;
        echo " : ";
        echo $val;
        echo "<br />";
    }
?>
</body>
</html>

結果は以下の通り。

HODENASU
OSYOSUI
TAMAGERU

0 : HODENASU 1 : OSYOSUI 2 : TAMAGERU

初めに書いたように、これは「配列」というものを理解していないと理解のしようがありません。

まず最初に「変数$arr」に3つの要素を持った配列を格納しました。で、この構造は、配列の要素の数だけループし、最初のループで「配列$arr」内の先頭の要素を「変数$val」に格納し、処理内でその変数を使う。2回目のループで「配列$arr」内の2番目の要素を「変数$val」に格納し、処理内でその変数を使う...という事を、配列の最後の要素に到達するまでループします。よって、配列の要素の数だけループされる事になります。

2番目の書き方では、条件式が「$arr as $key => $val」という形になっています。1番目の書き方では配列の要素のみが抽出されましたが、今回の書き方では、要素とそのインデックス(添え字)も一緒に抽出されます。「変数$key」に配列のインデックスが、「変数$val」に要素が格納されていきます。

また、「foreach文」は「オブジェクト(「クラス」のページで解説)」の「プロパティ(メンバ変数)(「クラス」のページで解説)」を走査すする事もできます。一応その方法だけ示した以下のサンプルをご覧下さい。

<html>
<body>
<?php
    class HODE{
        var $var1 = "HODENASU";
        var $var2 = "OSYOSUI";
        var $var3 = "TAMAGERU";
    }
    
    $obj = new HODE;

    foreach($obj as $val){
        echo $val;
        echo "<br />";
    }
    
    echo "<hr />";

    foreach($obj as $name => $val){
        echo $name;
        echo " : ";
        echo $val;
        echo "<br />";
    }
?>
</body>
</html>

結果は以下の通り。

HODENASU
OSYOSUI
TAMAGERU

var1 : HODENASU var2 : OSYOSUI var3 : TAMAGERU

まず最初に「変数$obj」に「HODE」クラス(「クラス」のページで解説)のオブジェクト(「クラス」のページで解説)を格納しました。今回のサンプルでは、オブジェクトが保持するプロパティ(メンバ変数)(「クラス」のページで解説)の数だけループし、各プロパティの値が抽出されます。

2番目の書き方では、「変数$name」にプロパティ名が、「変数$val」にプロパティの値が格納されていきます。

何れの場合も、「配列」、「オブジェクト」という特殊な変数について理解していないとしょうがないので、ここでは「foreach文」の使い方だけ解説しました。

その他の制御構造

ここまでで、連接構造による文(「単純文」と言う)と、選択構造による選択文、反復構造による反復文(選択文と反復文の2種類の文を「単純文」に対して「制御文」と言う)、つまり基本三構造の解説は完了です。

残念ながら、制御構造にはまだ、覚えなくてはならない事が残っています。「break」、「continue」、「declare」、「return」、その他諸々です(諸々って・・・)。で、ここで解説するのは「break」、「continue」の2つです。残りのものはページを改めて解説致します。

break文

この「break文」は、「switch文」の所で既に登場しました。改めて説明すると、「制御文から抜け出す働きを持つもの」です。次の2つのサンプルをご覧下さい。

<html>
<body>
<?php
    $hode = 1;
    while($hode){
        echo "HODENASU";
        echo "<br />";
        $hode = $hode + 1;
    }
?>
</body>
</html>
<html>
<body>
<?php
    $hode = 1;
    while($hode){
        if($hode == 5){
            break;
        }
        echo "HODENASU ";
        echo $hode;
        echo "<br />";
        $hode = $hode + 1;
    }
?>
</body>
</html>

1つ目のサンプルの結果は見事に「無群ループ」に陥ります。で、2つ目のサンプルは、1つ目のサンプルの「while文」の中に「if文」で「if($hode == 5){ break; }」を追記したものです。これの意味は、『もし「変数$hode」の値が「5」ならループから直ちに抜ける』です。よって、その結果は以下のようになります。ちなみに、サンプル中の「==」は、「等価比較演算子」というもので、「第1オペランド(左辺の被演算子)と第2オペランド(右辺の被演算子)の値を比較し、等しければ「真」を等しくなければ「偽」を返す」という働きをします(「演算子」のページで解説)。

HODENASU 1
HODENASU 2
HODENASU 3
HODENASU 4

「変数$hode」の値が「5」の時に直ちにループから抜け出しています。

更に次の3つのサンプルと結果をそれぞれご覧下さい。

<html>
<body>
<?php
    for($i = 1; $i <= 5; $i = $i + 1){
        for($j = 1; $j <= 5; $j = $j + 1){
            echo "HODENASU ";
            echo $i;
            echo " ";
            echo $j;
            echo "<br />";
        }
    }
?>
</body>
</html>
<html>
<body>
<?php
    for($i = 1; $i <= 5; $i = $i + 1){
        for($j = 1; $j <= 5; $j = $j + 1){
            if($j == 2){
                break;
            }
            echo "HODENASU ";
            echo $i;
            echo " ";
            echo $j;
            echo "<br />";
        }
    }
?>
</body>
</html>
<html>
<body>
<?php
    for($i = 1; $i <= 5; $i = $i + 1){
        for($j = 1; $j <= 5; $j = $j + 1){
            if($j == 2){
                break 2;
            }
            echo "HODENASU ";
            echo $i;
            echo " ";
            echo $j;
            echo "<br />";
        }
    }
?>
</body>
</html>
HODENASU 1 1
HODENASU 1 2
HODENASU 1 3
HODENASU 1 4
HODENASU 1 5
HODENASU 2 1
HODENASU 2 2
HODENASU 2 3
HODENASU 2 4
HODENASU 2 5
HODENASU 3 1
HODENASU 3 2
HODENASU 3 3
HODENASU 3 4
HODENASU 3 5
HODENASU 4 1
HODENASU 4 2
HODENASU 4 3
HODENASU 4 4
HODENASU 4 5
HODENASU 5 1
HODENASU 5 2
HODENASU 5 3
HODENASU 5 4
HODENASU 5 5
HODENASU 1 1
HODENASU 2 1
HODENASU 3 1
HODENASU 4 1
HODENASU 5 1
HODENASU 1 1

上記の3つのサンプルは、「for文」の中に更に「for文」という形をしています。このような形を「ネスト(入れ子)構造」と言います。で、1つめのサンプルは「break文」が無し、2つめのサンプルは「break文」があり、3つめのサンプルは「break文」があって、更に「break」の後ろに数字が付いています。2つ目と3つ目のサンプルは、『もし「変数$j」の値が「2」ならループから直ちに抜ける』というものですが、似たような形なのに結果が異なっています。それは、「break」の後ろに指定した数字が関係しています。この数字には、抜けるループの階層数を指定します。まず、ネストしていない「for文」の場合、階層数は「1」です。で、今回のサンプルは「for文」の中に更に「for文」が来ているので、階層数は「2」です。で、「break文」は、通常1階層分しかループから抜けません。なので、2つ目のサンプルでは1階層分しか抜けず、3つ目のサンプルでは一気に2階層分抜けたというわけです。ちなみに、「break文」に指定できる階層数の数字は当然、自然数です。また、実際の階層数以上の数字を指定するとエラーを発生します。今回のサンプルで言えば、2階層しかないので「3」を指定すると、エラーを発生します。

また、「反復文」のループから「switch文」で抜ける場合は、「break文」に指定する階層数は、「if文」の場合に指定する階層数に「1」加算したものにします。「switch文」でも「switch文」から抜けるために「break文」を使用しているからです。以下にサンプルのみ。

<html>
<body>
<?php
    $i = $j = 0;
    while(++$i){
        echo $i, " ";
        switch($i){
            default:
                break;
            case 10:
                break 2;
        }
    }
    echo "<br />";
    while(++$j){
        echo $j, " ";
        switch($j){
            default:
                continue;
            case 10:
                break 2;
        }
    }
?>
</body>
</html>

結果は以下のようになります。

1 2 3 4 5 6 7 8 9 10 
1 2 3 4 5 6 7 8 9 10 

continue文

この「continue文」は、「制御文の残りの処理を中断して、次のループに移る」という働きを持つものです。次のサンプルをご覧下さい。

<html>
<body>
<?php
    $hode = 1;
    while($hode){
        if($hode == 5){
            break;
        }
        echo "HODENASU ";
        echo $hode;
        echo "<br />";
        $hode = $hode + 1;
    }
    
    echo "<hr />";
    
    $hode = 1;
    while($hode){
        if($hode == 5){
            break;
        }
        if($hode == 2){
            $hode = $hode + 1;
            continue;
        }
        echo "HODENASU ";
        echo $hode;
        echo "<br />";
        $hode = $hode + 1;
    }
?>
</body>
</html>

結果は以下のようになります。

HODENASU 1
HODENASU 2
HODENASU 3
HODENASU 4

HODENASU 1 HODENASU 3 HODENASU 4

2つの「while文」は「変数$hode」の値が「5」の時に「break文」でループから抜けるという形ですが、2つ目の「while文」には更に『「変数$hode」の値が「2」の時に「変数$hode」に「1」加算だけして「continue文」で次のループに移る』という処理が追加されています。その結果、「変数$hode」の値が「2」の時だけ出力処理がスキップされています。

また、「continue文」でも、「break文」と同様に、「continue」の後ろに、次のループに移るのに飛ぶ階層数を指定する事が出来ます。

おさらいと予告

以上で、制御構造の基本的な解説は終了です。

制御構造とは

  • プログラムは、「連接構造」、「選択構造」、「反復構造」の「基本三構造」で成り立つ。
  • 「選択構造」による選択文には、「if文」、「else文」、「elseif文」、「switch文」がある。
  • 「反復構造」による反復文には、「while文」、「do...while文」、「for文」、「foreach文」がある。
  • それぞれの制御文(選択文と反復文の事)の処理は、条件式の値が「真」なら実行され、「偽」なら実行されない。
  • ループから抜ける「break文」と、次のループにスキップする「continue文」がある。

あなたは何型?"私"は文字列型

次回は、「型」について解説します。

作成日:2004年05月10日 最終更新日:2004年05月16日
【印刷モード風モード で表示】
ホーム > プロジェクトP > PHPの基本 > 制御構造