[Memo]PHP<制御構文> 2015.09.15
PHP 基本ここでは『独習PHP 第2版』で学んだポイントを箇条書きで記す。
スクリプトの構造
順次(順節、順構造) ― 記述された順番に処理を行う
選択 - 条件によって処理を分岐する
反復 - 特定の処理を繰り返し実行する
順次/選択/反復を組み合わせてプログラムを組み立てることを構造化プログラミングと言う
これは多くのプログラミング言語の基本的な考え方であり、PHPも含まれる
条件分岐(選択)
if命令(単純分岐)
if命令は、条件式がTRUEだった場合、次の{}内の処理を、FALSEだった場合、その次の{}内の処理を実行する
1 2 3 4 5 |
if(条件式) { //条件式がTRUEである場合に実行する処理 }else { //条件式がFALSEである場合に実行する処理 } |
1 2 3 4 5 6 7 8 |
<?php $x = 10; if ($x == 10) { print '変数$xは10です。'; } else { print '変数$xは10ではありません。'; } //結果: 変数$xは10です。 ?> |
また、TRUEだった場合にのみ処理を行いたい場合は、else以降を省略する
1 2 3 4 5 6 |
<?php $x = 10; if ($x == 10) { print '変数$xは10です。'; } //結果: 変数$xは10です。 ?> |
if命令(多岐分岐)
elseifを使用して、多岐分岐を表現する
1 2 3 4 5 6 7 8 9 |
if(条件式1) { //条件式1がTRUEである場合に実行する処理 } elseif(条件式2) { //条件式2がTRUEである場合に実行する処理 } …… //必要な分岐の数だけ列記 } else { //条件式1、2、……がいずれもFALSEだった場合に実行する処理 } |
1 2 3 4 5 6 7 8 9 10 11 12 |
<?php $x = 15; if($x > 20) { print '変数$xは20より大きいです。'; } elseif($x > 10) { print '変数$xは10より大きく、20以下です。'; } elseif($x > 5) { print '変数$xは5より大きく、10以下です。'; }else { print '変数$xは5以下です。'; } //結果: 変数$xは10より大きく、20以下です。 ?> |
条件式が複数合致しても、最初に合致した条件式のブロック({})一つだけが実行される
ネスト(入れ子構造)
制御命令同士を入れ子にすることを「ネストする」という
ネストすることによって、分岐をより細かくすることができる
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?php $x = 1; $y = 0; if($x == 1) { if($y == 1) { print '変数$x、$yは1です。'; }else { print '変数$xは1ですが、$yは1ではありません。'; } } else { print '変数$xは1ではありません。'; } //結果: 変数$xは1ですが、$yは1ではありません。 ?> |
if命令以外にも、switch、for/foreach、while/do~whileなどの制御命令でもネストできる
switch命令(多岐分岐)
switch命令は、「等価演算子による多岐分岐」に特化した条件分岐である
switch命令を利用することで、同じような式を繰り返し記述する手間を省き、コードが短くなる
1 2 3 4 5 6 7 8 9 |
switch(式) { case 値1: //「式=値1」である場合に実行する処理 case 値2: //「式=値2」である場合に実行する処理 …… //必要な分岐の数だけ列記 default: //式が値1、2、……のいずれでもない場合に実行する処理 } |
以下の例はif命令で書いた場合
1 2 3 4 5 6 7 8 9 10 11 |
<?php $rank = '優'; if($rank == '優') { print '大変良いです。'; } elseif($rank == '良') { print '良いです。'; } elseif($rank == '可') { print 'もう少し頑張りましょう'; } else { print '???'; } |
以下の例はswitch命令で書いた場合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
$rank = '優'; switch($rank) { case'優': print '大変良いです。'; break; //break命令でブロックから脱出 case'良': print '良いです。'; break; case'可': print 'もう少し頑張りましょう'; break; default: print '???'; break; } //結果: 大変良いです。 ?> |
break命令は、各ブロックの終わりに必ず記述する
記述しないと、後続の命令がすべて実行されてしまう
ただし例外として、caseA、caseB、caseCのいずれかに当てはまる時、処理を実行したい場合は、空のcaseを列記する
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<?php $title = 'ドラゴンクエスト'; switch ($title) { case 'ファイナルファンタジー': case 'ドラゴンクエスト': case 'キングダムハーツ': print $title . 'は、スクウェア・エニックスのゲームソフトです。'; break; case 'メタルギアソリッド': case '幻想水滸伝': print $title . 'は、コナミのゲームソフトです。'; break; } //結果: ドラゴンクエストは、スクウェア・エニックスのゲームソフトです。 ?> |
また、switch命令は、式と値との比較を==演算子で行う(===ではない)
そのため、文字列リテラルと数値リテラルを比較した場合、文字列は数値へと変換されるので注意する
例えば、$bar = ‘X’、case ‘0’、case ‘X’の順でコードが書かれていた場合、Xは0に変換され、先にcase ‘0’の方に合致する
繰り返し処理(反復)
while/do~while命令
while/do~while命令は、与えられた条件式がTRUEである間、ループを繰り返す
1 2 3 |
while(条件式) { //条件式がTRUEである間、繰り返し実行する処理 } |
1 2 3 |
do { //条件式がTRUEである間、繰り返し実行する処理 }while(条件式); |
do~while命令の末尾にはセミコロンが必須
1 2 3 4 5 6 7 |
<?php $i = 1; while($i < 6) { print "{$i}番目のグループです。<br>"; $i++; } ?> |
実行結果:
1番目のグループです。
2番目のグループです。
3番目のグループです。
4番目のグループです。
5番目のグループです。
1 2 3 4 5 6 7 |
<?php $i = 1; do { print "{$i}番目のグループです。<br>"; $i++; }while($i < 6); ?> |
実行結果:
1番目のグループです。
2番目のグループです。
3番目のグループです。
4番目のグループです。
5番目のグループです。
上記の例はどちらも同じ結果だが、値を$i = 6;に変更した場合、while命令では何も実行されないのに対し、do~while命令は1回だけ処理が実行される
これは、while命令は前置判定で、do~while命令は後置判定という違いによるもの後置判定は、条件にかかわらず、必ず1回だけ処理が実行される
無限ループ
ループは条件がFALSEにならないと終了しない
もし、終了しない場合、無限に処理が繰り返され、最悪の場合フリーズしてしまう
これを無限ループという
for命令
for命令はあらかじめ指定された回数だけ処理を繰り返す
1 2 3 |
for(初期化式:ループ継続条件式;増減式) { //ループ内で実行する処理 } |
1 2 3 4 5 |
<?php for($i = 1; $i < 6; $i++) { print"{$i}番目のグループです。<br>"; } ?> |
実行結果:
1番目のグループです。
2番目のグループです。
3番目のグループです。
4番目のグループです。
5番目のグループです。
上記の例は、while命令の例と同じ意味
for命令では、まず初期化式が実行される(初回のみ)
続いてループ継続条件式でTRUEならばブロック内の処理を実行(FALSEならばfor命令を終了する)、その後増減式を実行する
これをループ継続条件式がFALSEになるまで繰り返す
カンマ演算子(,)
カンマ演算子(,)を使用すると、初期化式、ループ継続条件式、増減式に複数の式を指定できる
カンマ演算子で繋いだ式は先頭から実行される
1 2 3 4 5 |
<?php for($i = 1, $j = 1; $result = $i * $j, $i < 6; $i++, $j++) { print "{$i} × {$j} = {$result}<br>"; } ?> |
実行結果:
1 × 1 = 1
2 × 2 = 4
3 × 3 = 9
4 × 4 = 16
5 × 5 = 25
ここではまず、$i=1, $j=1が実行され、
続いて$iと$jを乗算し$resultへ代入、$i<6が実行、そしてTRUEならばprint文の処理が実行され(FALSEなら終了)、
最後に$i++, $j++が実行されている
初期化式、ループ継続条件式、増減式はあくまで便宜上の命名であり、実際は自由な式を記述できる
foreach命令
foreach命令は、指定された配列/連想配列に対して、先頭から順に繰り返し処理を行う
1 2 3 4 5 6 7 8 9 |
//配列の場合 foreach(配列 as 値変数) { //ループ内で実行する処理 } //連想配列の場合 foreach(連想配列 as キー変数 => 値変数) { //ループ内で実行する処理 } |
キー変数/値変数(仮変数)は、配列や連想配列から取り出した各要素のキー/値を一時的に格納する変数
foreachのブロック内では、この仮変数を介して個々の要素にアクセスする
1 2 3 4 5 6 |
<?php $data = array('本田','香川','長谷部','宇佐美'); foreach($data as $value) { print "私は{$value}です!<br>"; } ?> |
実行結果:
私は本田です!
私は香川です!
私は長谷部です!
私は宇佐美です!
1 2 3 4 5 6 |
<?php $data = array('本田'=>'FW','香川'=>'MF','長谷部'=>'MF','宇佐美'=>'FW'); foreach($data as $key => $value) { print "{$key} : {$value}<br>"; } ?> |
実行結果:
本田 : FW
香川 : MF
長谷部 : MF
宇佐美 : FW
値変数の参照渡し
foreachブロックの中で、配列/連想配列の要素を変更したい時、値変数を参照渡しする必要がある
※参照渡しとは、値を格納したメモリ上のアドレスをコピーすること
$x = 1 → $y =& $x → $x = 5 //結果:$yも5になる
1 2 3 4 5 6 7 |
<?php $data = array('本田','香川','長谷部','宇佐美'); foreach($data as &$value) { $value = $value . '選手'; } print_r($data); ?> |
実行結果:
Array ( [0] => 本田選手 [1] => 香川選手 [2] => 長谷部選手 [3] => 宇佐美選手 )
foreach命令で値($value)を一つずつ取り出し、’選手’を付加している
通常、foreach命令では配列要素を値渡し(値そのものをコピー)しているため、値変数に対する操作は元の配列には影響しない
しかし、ここでは「&$value」と「&」演算子を使って、参照渡ししているため、値変数への操作が元の配列の値にも反映されている
ループの制御
break命令
break命令は、現在のループを強制的に中断する命令
1 2 3 4 5 6 7 8 |
<?php $sum = 0; for ($i = 1; $i <= 100; $i++) { if($sum > 1000) {break;} $sum += $i; } print '合計が1000を超えるのは、1~' . --$i . 'を加算したときです。<br>'; ?> //結果: 合計が1000を超えるのは、1~45を加算したときです。 |
0 + 1 = 1
1 + 2 = 3
3 + 3 = 6
…
903 + 43 = 946
946 + 44 = 990
990 + 45 = 1035
上記の例は、$sumに$iを加算していき、$sumの値が1000を超えたところでループから脱するというコード
ポイントとして、break命令はif命令等の条件分岐と組み合わせて使用する点
また、ループから脱しても、for命令の増減式($i++)は実行されている点である
(そのためprint文では –$i と、-1減算している)
continue命令
continue命令は、現在の周回だけをスキップし、ループそのものは継続して実行させる命令
1 2 3 4 5 6 7 8 |
<?php $sum = 0; for($i = 1; $i <= 100; $i++) { if($i % 2 != 0){ continue;} $sum += $i; } print "合計値は{$sum}です。"; //結果: 合計値は2550です。 ?> |
0 + 2 = 2
2 + 4 = 6
6 + 6 = 12
…
2256 + 96 = 2352
2352 + 98 = 2450
2450 + 100 = 2550
上記の例は、$sumに$iの偶数だけを加算していくコード
$i % 2 != 0 は2で割って、余りが0以外、つまり奇数のこと
これをcontinue命令でスキップすることで、偶数だけが加算されていく
ループのネストとbreak/continue命令
ネストされたループの中で、break/continue命令を使用した場合、通常は最も内側のループを脱出/スキップする
1 2 3 4 5 6 7 8 9 10 |
<?php for($i = 1; $i < 10; $i++) { //外側のループ for($j = 1; $j < 10; $j++) { //内側のループ $result = $i * $j; if($result > 40) { break; } print "{$result} "; } print '<br>'; } ?> |
実行結果:
1 2 3 4 5 6 7 8 9
2 4 6 8 10 12 14 16 18
3 6 9 12 15 18 21 24 27
4 8 12 16 20 24 28 32 36
5 10 15 20 25 30 35 40
6 12 18 24 30 36
7 14 21 28 35
8 16 24 32 40
9 18 27 36
ここでは、$resultの値が40を超えたらbreak命令を実行している
これによって、内側のループを脱出している
一方で、一度でも値が40を超えたら出力を停止させたい場合、以下のように書き換える
1 2 3 4 5 6 7 8 9 10 |
<?php for($i = 1; $i < 10; $i++) { for($j = 1; $j < 10; $j++) { $result = $i * $j; if($result > 40) { break 2; } //書き換え print "{$result} "; } print '<br>'; } ?> |
実行結果:
1 2 3 4 5 6 7 8 9
2 4 6 8 10 12 14 16 18
3 6 9 12 15 18 21 24 27
4 8 12 16 20 24 28 32 36
5 10 15 20 25 30 35 40
break命令の末尾にループの階層を指定するとその階層分のループを脱出する
continue命令も同様の方法
その他
スクリプトブロックと固定テンプレート
PHPページにおいて、スクリプティングデリミタ(<?php ~ ?>)で囲まれた箇所をスクリプトブロック
また、それ以外の箇所を固定テンプレート(HTMLテンプレート)と呼ぶ
固定テンプレート部分はprint命令と等価であると言える
そのため、制御命令文の途中に固定テンプレートが含まれていても、正しく実行される
1 2 3 |
<?php for($i = 1; $i < 6; $i++) { ?> <p>HelloWorld!!</p> //固定テンプレート <?php } ?> |
実行結果:
HelloWorld!!
HelloWorld!!
HelloWorld!!
HelloWorld!!
HelloWorld!!
制御命令の別構文
if、switch、while、for、foreach命令には、別の構文がある
中カッコ({ ~ })の代わりに、開始をコロン(:)、終了をendif、endswitch、endwhile、endfor、endforeachのいずれか、また途中のelseif、elsenoの開始はコロン(:)で表す
1 2 3 4 5 6 7 8 9 10 |
<?php $x = 35; if($x > 20): print '変数$xは20より大きいです。'; elseif($x > 10): print '変数$xは10より大きく20以下です。'; else: print'変数$xは10以下です。'; endif; //結果:変数$xは20より大きいです。 ?> |