PHP/制御構造

制御構造とは、プログラムの実行順序を変更するための構造のことを指します。PHPには、様々な制御構造が用意されており、プログラムを効率的に制御することができます。 この章では、制御構造の中でも代表的な「条件分岐」と「繰り返し」について解説します。 条件分岐には「if文」「switch文」「match文」があり、繰り返しには「for文」「while文」「do-while文」があります。 それぞれの文法や使い方を理解し、プログラムの制御に活用していきましょう。
条件分岐は、プログラムにとって非常に重要な要素であり、実行する命令文の流れを切り替えるために使用されます。 条件分岐を使用することで、特定の条件が満たされた場合にのみ、特定の命令文が実行されるようにすることができます。
PHPには、if, switch, match の3つの分岐構文があります。
以下に、if文、switch文、match式の利点と欠点を表にまとめました。
それぞれの構文には利点と欠点があり、使用する際にはその目的に応じた最適な構文を選択する必要があります。
if文は、複雑な条件分岐をカバーすることができますが、ネストが深くなりやすいため見づらくなることがあります。
switch文は、複数の分岐を一つの構文で書けるため、見やすいという利点がありますが、比較演算子が単純な場合にしか使えず、フォールスルーに注意が必要です。
match式は、値に基づいて分岐でき、見やすく分かりやすいという利点がありますが、正規表現を使う場合には不向きです。
PHPには、C風のifがあります。else ifの短縮構文があるほか、テキストに埋込むのに適した代替構文があります。
例:
PHPには、C風のswitchがあり、フォールスルーの挙動などほとんど同じですが、case の式に定数式以外の式が使える他、文字列などの比較も「緩やかな比較」で行えます。
PHPのmatchは、switchと似ていますが、文ではなく式なので値が取れるほか、比較には「厳密な比較」が使われます。
matchには、代替構文も埋込み構文もありません。
分岐処理を多重にネストすると、可読性が低下し、コードが複雑になります。また、ネストされた分岐により、バグを見つけることがより困難になる場合があります。
そのため、分岐処理をシンプルに保つために、以下の点に注意することが重要です。
以上のようなポイントに注意することで、分岐処理をシンプルに保つことができます。
ガード節は、プログラムにおいて条件式が満たされない場合に、関数の実行を早期に終了させる方法です。通常、条件式が満たされなかった場合には関数内で複数のif文が使われている場合がありますが、ガード節を使うことで、コードを簡潔に保ち、可読性を高めることができます。
例えば、次のような関数があったとします。
この関数では、引数が数値でない場合に、0を返しています。しかし、この関数は、引数が数値でない場合はすぐに処理を終了させる必要があります。この場合、ガード節を使うことで、以下のように書き換えることができます。
このように、ガード節を使うことで、コードの可読性を高めることができます。

省略表記や三項演算子を使用すると、コードの可読性を向上させることができます。以下は、その書き方の例です。
【省略表記】
【null合体演算子】 null合体演算子??を使用することで、変数のnullチェックを簡潔に書くことができます。
【switch文の省略表記】 switch文の省略表記を使用することで、複数の条件に対して同じ処理を行うことができます。
ただし、省略表記や三項演算子を多用しすぎると可読性が低下するため、適切な場面で使用するようにしましょう。また、複雑な条件分岐には適していないため、その場合は通常のif文やswitch文を使用することが望ましいです。
if や while なでの条件式で、使われる比較演算子には2種類あります。
なお、=等号1個は単なる代入命令ですが条件式で使われると代入された値を真理値として評価されます。
==は、型を厳格には区別しない「緩やかな比較」演算子です。
===は、型まで一致していることを要求する「厳密な比較」演算子です。
!==は型まで一致していない、あるいは値が一致していないと真をかえす演算子です。
繰り返しは、同じ処理を複数回繰り返すことができる制御構造の一つです。ループとも呼ばれ、同じ処理を繰り返し実行することで、膨大な量の処理を自動化することができます。繰り返し処理は、プログラミングにおいて非常に重要な役割を果たしており、Webアプリケーションの開発でも頻繁に利用されます。
ここでは、PHPで繰り返し処理を行うための方法を学びます。まずは、基本的な「for文」、「while文」、「do-while文」の使い方を解説します。 次に、より高度な繰り返し処理に必要な概念である「配列」や「連想配列」、そして「foreach文」の使い方についても学びます。
PHPには、while, do-while, for, foreach の4つの繰り返し文と、break, continue の2つの繰り返し制御文があります。
また、goto 演算子はありますが、ループからの大域脱出はbreak, continue の引数(オプション;ディフォルトは 1)でループのレベルを変えるなど、goto が使われがちな状況に代替手段を提供しているので、ほかのプログラミング言語ほどは goto の出番はありません。
加えて、PHPの繰り返し文や複文は、スコープを持ちません。ループを抜けてもループ変数は「生きている」ので、ループ変数は参照可能です。
whileは、まず条件式を評価し、真なら続く文(単文あるいは複文)を実行し条件式を再び評価します。もし、偽ならばループの次に移ります。
do-whileは、文(単文あるいは複文)を実行し条件式を評価します。真なら文を再び評価します。もし、偽ならばループの次に移ります。
forは、C風の3つの項を持つfor文です。
#whileの例と同じロジックを for(;;) で書き直しました(結果は同じなので省略します)。
foreachは、配列に代表される「繰り返し可能オブジェクト」(iterable object)を繰り返しします。
foreachには、配列版と連想配列版があります。
ループ変数を、参照にすることで配列の要素を変更できます。
このコードでは、まず配列 $ary を定義しています。その後、foreachループを使って配列 $ary の要素を 2 倍に更新し、変数 $value に参照をとることで配列の値が更新されるようにしています。つまり、foreachループが終了した時点で、配列 $ary の中身は、すべて 2 倍になっています。
その後、$value 変数に 0 を代入していますが、foreachループ内で参照していたのは $ary 配列の要素の参照であり、変数 $value 自体は配列要素への参照ではありません。そのため、$value に 0 を代入しても、配列 $ary の最後の要素だけが 0 に更新されることになります。
このように、ループ変数は、foreach()を抜けても参照は生きているので、代入するとループの外からも配列を壊すことができてしまいます。
break文は、ループ内で使用され、ループ処理を中断するために使用されます。break文はif文内に配置されることができます。ループ内でbreak文が実行されると、ループは即座に終了し、次の処理に進みます。
以下は、ループ処理中にbreak文を使用する例です。
この例では、1から10までの数字を表示しますが、6の前に処理が停止します。
continue文は、ループ内で使用され、現在のループの反復をスキップして、次の反復に進むために使用されます。
以下は、ループ処理中にcontinue文を使用する例です。
この例では、1から10までの数字を表示しますが、6だけをスキップします。
goto文は、指定されたラベルにジャンプするために使用されます。goto文は、ループ、スイッチ、または関数の中で使用されます。ただし、goto文を使用することは、プログラムの可読性を損なうことがあり、使用は推奨されません。
以下は、goto文を使用する例です。
この例では、goto文が使用され、aというラベルにジャンプします。これにより、2番目のecho文が表示されず、3番目のecho文だけが表示されます。
例外処理(れいがいしょり、exception handling)とは、プログラム実行中に予期せぬ異常が発生した場合に、通常の実行フローを中断し、エラーメッセージの表示や適切な処理を行うプログラムの手法です。
PHPでの例外処理は、try, catch, throw, finally キーワードを使って行われます。例外が発生する可能性のあるコードを try ブロック内に記述し、それに対する例外処理を catch ブロックで行います。
以下は基本的な例です:
上記の例では、try ブロック内で例外が発生する可能性があります。もし例外が発生した場合、catch ブロックが実行されて例外オブジェクトが $e としてキャッチされ、その後の処理が実行されます。finally ブロックは例外の有無にかかわらず、最終的な処理を実行するために使用されます。
以下はゼロ除算の例外処理を含んだPHPコードです。
この例では、divide() 関数を定義し、引数 $numerator を $denominator で割る処理を行います。try ブロック内で $denominator がゼロの場合に例外を投げます。catch ブロックでは例外が発生した場合にそのメッセージを表示し、finally ブロックでは最終的なクリーンアップを行います。
PHPの例外処理に関連する主なクラスは次のとおりです。
カスタム例外を作成することもできます。例えば、特定の種類のエラーやアプリケーション固有の例外を処理するために、以下のようにしてカスタム例外を作成することができます:
上記の例では、CustomException という独自の例外クラスを作成しています。そして try ブロック内で、何かしらの条件でその例外を発生させ、catch ブロックでその例外をキャッチしています。
このようにして、標準の Exception クラスを継承してカスタム例外を作成し、それを使用して特定の種類の例外を処理することができます。
PHPにおける例外処理のベストプラクティスにはいくつかあります。その中でも重要なものをいくつか挙げてみましょう。
これらのベストプラクティスを遵守することで、PHPアプリケーションのエラー処理を効果的に行うことができます。
代替構文は、通常の制御構造の代わりに、より読みやすいコードを書くために使用される構文です。 代替構文は、制御構造の一部に波括弧 { } を含めずに書くことができ、それによってコードをよりシンプルにすることができます。
例えば、次のif文の代替構文は:
以下のように書くことができます:
同様に、以下のfor文の代替構文は:
以下のように書くことができます:
代替構文は、コードの可読性を向上させることができますが、適切に使用しない場合はコードの可読性を損なうこともあります。したがって、代替構文を使用する際には、適切に判断することが重要です。
代替構文は、コードの見た目をより読みやすくするために導入された構文です。 代替構文を使用する場合、制御構造の終了を示すためにそれぞれ endif、endfor、endforeach、endwhile を使用します。 しかし、代替構文を使っても制御構造自体の動作には変わりはありません。