PHP入門 ≫ LESSON9 分岐・繰り返し

分岐・繰り返し・条件式

PHPでは、プログラム中で処理を分岐したり繰り返したりすることができます。
分岐や繰り返しを行う処理には、条件式が必要になります。
その条件の結果がtrueなら繰り返しとか、falseなら繰り返しを終了するなど、分岐や繰り返しを行うかどうかの条件です。

この条件式には、主に比較演算子をつかった判定文を使います。

if-else文

もし○○だったら~~~をする、○○でなかったらXXXXをする、というような処理を行うのがif-elseです。いくつか使い方があるので見ていきましょう。

● if (expr1) ブロック形式

if (条件式) {
    処理;
}

もしも条件式が真なら、処理を行います。

$age = 21;
if ($age >= 20) {
    echo "20 over!\n";
}

結果は以下。

20 over!



● if (expr1) ブロック else ブロック形式

if (条件式) {
    処理1;
} else
    処理2;
}

もしも条件式が真なら、処理1を行います。それ以外なら処理2を行います。

$age = 19;
if ($age >= 20) {
    echo "20 over!\n";
} else {
    echo "20 under!\n";
}

結果は以下。

20 under!



● if (expr1) ブロック else if (expr2) ブロック else ブロック形式

if (条件式1) {
    処理1;
} else if (条件式2) {
    処理2;
} else {
    処理3;
}

もしも条件式1が真なら、処理1を行います。
それ以外でもしも条件式2が真なら処理2を行い、それ以外なら処理3を行います。
else ifブロックは増やせます。

$age = 19;
if ($age >= 20) {
    echo "20 over\n";
} else if ($age >= 15) {
    echo "15 - 19\n";
} else if ($age >= 10) {
    echo "10 - 14\n";
} else {
    echo "10 under\n";
}

結果は以下。

15 - 19





switch文

式に一致した値の処理を行います。

switch (式) {
    case 値1:
        処理1_1;
        処理1_2;
        break;
    case 値2:
        処理2_1;
        break;
    default:
        どれにも一致しない場合の処理;
}

もしも式1の値が値1と一致したなら、処理1_1と処理1_2を行います。
行う処理は1つでも複数でもかまいません。最後にbreak;をつけることで、それ以上の処理を行いません。1つのcaseで行う処理は、{ }で括る必要がありません。

値1と一致しなければ値2と比較します。一致すれば処理を行います。
caseはいくつでも増やす事ができ、最後にdefault:をつけると、どれにも一致しなかった場合の処理が実行されます。

$hour = 12;
switch ($hour) {
    case 0:
        echo '0時です。早く寝ましょう';
        break;
    case 6:
        echo '6時です。起きる時間です';
        break;
    case 12:
        echo '12時です。お昼の時間です';
        break;
    default:
        echo 'メッセージはありません';
}

結果は以下。

12時です。お昼の時間です

値の部分は、条件式のような「○以上」というようなものをいれることはできません。ズバリ、一致する値を定義します。
また、各case処理の最後にbreak:をそれぞれ入れないと、一致したcaseから先の処理を、次のbreakが出るまですべての処理を無条件で行ってしまいます。気をつけましょう。

while文

条件式に一致している間処理を繰り返して行う、という繰り返しはwhileを使います。

● while (expr1) ブロック形式

while (条件式) {
    処理;
}

条件式が真の間は、処理を繰り返して行います。

$i = 0;
while ($i < 5) {
    echo "$i\n";
    $i++;
}

結果は以下。

0
1
2
3
4

$iの値が5より小さいときは繰り返しを行います。$iの値はインクリメントしているので、5以上になったら繰り返しを抜けます。



注意

ループ処理を行う場合、プログラムの書き間違いでループが終了せずに無限に繰り返し処理を行ってしまう場合があります。

コマンドプロンプトでいつまでたっても処理が終わらず次のプロンプトが戻ってこなかったり、無間ループに入ってしまったことに気付いたら、すぐにプロンプト画面をアクティブにした状態で、Ctl-C(コントロールキーを押しながらCを押す)をやりましょう。処理が中断できます。



● do ブロック while (expr);形式

do {
    処理;
} while (条件式);

最初に必ず一度処理を行います。
処理条件式が真の間は、処理を繰り返して行います。

$i = 0;
do {
    echo "$i\n";
    $i++;
} while ($i < 5);

結果は以下。

0
1
2
3
4



インクリメント、デクリメント

変数をインクリメント、デクリメントして繰り返し判定に使うことが多いです。
何気なく使ってますが、ちょっと注意が必要です。

$i++

は、$iの値を使ってからインクリメントします。
この場合、$i<5と比較してから、$iの値を1プラスしている状態です。
これを、

++$i

とかくと、インクリメントしてから$iの値を使います。
なので、最初の判定のときは$iの値は1になってます。結果は1~4までの出力になります。

echo $i++;

の場合は$iの値を出力してからインクリメントしますが、++$iの場合、インクリメントされた値が出力されます。

$i++;のように単体で使う場合はあまり関係ありませんが、他のものと同時に使う場合は注意しましょう。



for文

○回繰り返す、などと最初から繰り返し回数が決まっているものはforを使うと便利です。

● for (expr1;expr2;expr3) ブロック形式

for (初期化; 条件式; ループ処理) {
    処理;
}

最初に初期化の部分を実行します。
そして、条件式が真の間は処理を繰り返して行います。
一回の繰り返しの最後にはループ処理を行い(大抵変数のインクリメント・デクリメント)条件式を判定してからまた処理を行います。

for ($i = 0; $i < 5; $i++) {
    echo "$i\n";
}

結果は以下。

0
1
2
3
4

$iが0から5より小さい間は繰り返します。
初期化をforの外に出して、ループ処理はブロックの中に含めても同じです。

$i = 0;
for (; $i < 5;) {
    echo "$i\n";
    $i++;
}

ない項目があっても区切りの「;」は忘れないようにしましょう。



foreach文

配列などのリストの内容に対してすべて順に処理を行いたいときに使うと便利です。

● foreach (list) ブロック形式

foreach (リスト as 変数) {
    処理;
}

foreach (リスト as キー => 変数) {
    処理;
}

リストのすべての値を一つ一つ変数に代入し処理を行います。

$list = array('user1', 'user2', 'user3');
foreach ($list as $usr) {
    echo "$usr\n";
}

結果は以下。

user1
user2
user3



連想配列の場合、asのあとにキー、「=>」でその値をとる事ができます。

$list = array('user1'=>'name1', 'user2'=>'name2', 'user3'=>'name3');
foreach ($list as $k => $v) {
    echo $k . ' ' . $v . "\n";
}

結果は以下。

user1 name1
user2 name2
user3 name3





ループ制御

while,for,foreachのループブロックでは、プログラムの流れを制御することができます。

制御の前にラベル(label)について説明しましょう。
プログラム中の各場所に

ラベル名: while ..

という形式でラベルを付けることができます。
そこに移動せよ!と制御することができるのですが、あまり使わない方がいいかもしれません。 使わなくても問題ありません。
注)ラベルはループに限らずプログラム中どこでも使えます。

● goto label

goto ラベル名;

ラベル名 : 処理

ラベルの位置に処理を移します。
これはループではない場所でも有効です。

echo "1\n";
goto label1;
echo "2\n";
label1 : echo "3\n";

結果は以下。

1
3



● break

break;

ループを終了します。 二重のループであれば、最も手前(最近)ループを終了します。
二重のループを一気に抜けたい場合は、gotoを利用します。

$i = 0;
while ($i < 100) {
    echo "$i\n";
    $i++;
    if($i >= 5) { break; }
}

for($j = 0; $j < 10; $j++) {
    $i = 0;
    while ($i < 10) {
        echo "$j $i\n";
        $i++;
        if($i >= 5) { goto label1; }
    }
}
label1:

結果は以下。

0
1
2
3
4
0 0
0 1
0 2
0 3
0 4



● continue;

continue;

すぐに繰り返しブロックを終了し、次のループを実行します。

$i = 0;
while ($i < 7) {
    $i++;
    if($i >= 5) { continue; }
    echo "$i\n";
}

結果は以下。

1
2
3
4



論理演算子

条件式が複数ある条件、全ての条件を論理演算子でつないで、その結果を全体の判定結果とします。

論理演算子
a && b論理 AND
a,bともにtrueならtrue・それ以外はfalse
a and b論理 AND
a,bともにtrueならtrue・それ以外はfalse
a || b論理 OR
a,b少なくともどちらか一方がtrueならtrue・それ以外はfalse
a or b論理 OR
a,b少なくともどちらか一方がtrueならtrue・それ以外はfalse
a xor b排他的論理 OR
a,bどちらかがtrueでかつ両方ともtrueでない場合true

&&とand、||とorはそれぞれ同じです。が、優先順位はそれぞれandとorのほうが低いです。


● (expr1) && (expr2)

条件がすべてtrueならばtrue、それ以外はfalseになります。

for($age = 0; $age < 5; $age++) {
    echo "$age ";
    if (($age >= 2) && ($age < 4)) {
        echo "2-4\n";
    } else {
        echo "else\n";
    }
}

結果は以下。

0 else
1 else
2 2-4
3 2-4
4 else



● (expr1) || (expr2)
条件がどちらか一つでもtrueならtrue、それ以外はfalse になります。

for($age = 0; $age < 5; $age++) {
    echo "$age ";
    if (($age == 2) || ($age == 4)) {
        echo "2 or 4\n";
    } else {
        echo "else\n";
    }
}

結果は以下。

0 else
1 else
2 2 or 4
3 else
4 2 or 4



論理演算の結果よっては、後半の判定をするかしないか分かれます。

$a = 1;
$b = -1;

if($a > 0 && $b++ > 0) echo "両方正数\n";

echo $a . ':' . $b;

結果は以下。

1:0

「$a > 0」の判定結果はtrueです。&&では両方trueの場合のみtrueなので、後半の結果により、最終的な結果が出されます。なので、後半の「$b++ > 0」も実行します。
結果はfalseなので、「echo "両方正数\n";」は実行されませんが、$b++は実行されていますので、$bの値はインクリメントされて0になります。

これを、$aの値を0に設定すると、

0:-1

となります。これは、最初の「$a > 0」の判定結果はfalseなので、右側の値がどういう結果になろうともうfalse確定なので、右側の判定が行われません。
なので、$bのインクリメントも行われませんでした。

||の場合も見てみましょう。

$a = 1;
$b = -1;

if($a > 0 || $b++ > 0) echo "少なくとも片方が正数\n";

echo $a . ':' . $b;

結果は以下。

少なくとも片方が正数
1:-1

||では、前半の結果がtrueなので、後半何をもってきてもtrue確定なので、後半の処理を行いません。なので、$bのインクリメントも行われませんでした。

$aに0を設定すると、前半がfalseでも後半がtrueであればtrueになるので、後半も実行して、$bもインクリメントされます。結果は「0:0」が出力されます。


演算子の優先順位

演算子は、普通の四則演算と同じで優先順位があります。

演算子の優先順位
new
[
**
~ ++ -- (int)など @
instanceof
!
* / %
+ - .
<< >>
< <= > >=
== != === !== <> <=>
&
^
|
&&
||
??
?:
= += -= *= **= /= .= %= &= |= ^= <<= >>=
and
xor
or

*や%は、+や-より優先順位が高いです。これは普通の四則演算と同じです。
それほど気にする必要はないと思いますが、ちょっと疑問に思った組み合わせがあればチェックしておきましょう。

&&とandは意味は同じですが、&&のほうが優先順位が高いです。andは「=」などよりも低いです。
ちょっとやってみます。

$r = true && false;
var_dump($r);

$r = true and false;
var_dump($r);

結果は以下。

bool(false)
bool(true)

前半では、「true && false;」が優先されて、結果のfalseが$rに代入されます。
後半は、「$r = true」が優先されるので、$rの結果はtrueになります。


その他の演算子

○ expr1 ? expr2 : expr3
expr1がtrueならばexpr2を、falseならばexpr3を返します。

$i = -1;
$r = $i >= 0 ? '正数' : '負数';
echo $r;

結果は以下。

負数



ページのトップへ戻る