PHPで例外処理を「try catch」でハンズオン実装
「try catch」は、PHPで例外処理を行うための構文です。
そもそも例外処理を導入する理由は?
例外処理は、通常のフローでは扱いきれないエラーを処理するための機能です。
例えば、「ファイルが存在しない」や「データベースに接続できない」場合です。 このような場合、Fatal Errorが発生してプログラムが異常終了します。
それでもプログラムを止めたくない場合にtry catchを使います。
他にも例外処理を使用する理由はあります
- プログラムを異常終了させない
- 例外オブジェクトを取得してデバッグ
- ログの出力
シンプルな例外処理の実装
try catchの基本構文
<?php
try {
// 例外が発生するかもしれない処理
// ファイルの存在確認や、データベースの接続確認など
} catch (Exception $e) {
// 例外が発生したときの処理
// 異常終了せずに、ここで処理を継続する
}
ゼロ除算の例
<?php
function divide($a, $b) {
if ($b === 0) {
throw new Exception("ゼロ除算だ。何やってんだ。");
}
return $a / $b;
}
try {
echo divide(10, 0);
} catch (Exception $e) {
echo "例外発生: " . $e->getMessage();
}
実行結果
例外発生: ゼロ除算だ。何やってんだ。
解説
大枠の流れは以下の通りです。
- 例外を定義する
- 例外を発生させる
- 例外をキャッチする
下記に順番に説明していきます。
例外クラス(Exception)を定義する
function divide($a, $b) {
if ($b === 0) {
throw new Exception("ゼロ除算だ。何やってんだ。");
}
return $a / $b;
}
例外の定義とは例外クラスのインスタンス化です。
スローすることで例外処理を起動させることができます
new Exception()で例外オブジェクトのインスタンス化だけでは不十分で throw new Exception()で例外をスローする必要があります。
例外クラスの継承関係
Throwable (インターフェース)
├── Error
│ ├── ParseError
│ ├── TypeError
│ └── ...
└── Exception
├── LogicException
│ ├── BadFunctionCallException
│ ├── DomainException
│ └── ...
├── RuntimeException
│ ├── OutOfBoundsException
│ ├── OverflowException
│ └── ...
└── ...
例外が発生したらどうなる?
現行の処理フローが中断され、catchブロックに移行します。
try {
throw new Exception("ゼロ除算だ。何やってんだ。");
// 例外が発生したら、ここで処理が中断される
echo "例外が発生したら中断されるため、ここは実行されない";
} catch (Exception $e) {
echo "例外発生: " . $e->getMessage();
}
実行結果
「例外が発生したら、ここで処理が中断される」は出力されず下記の表示です。
例外発生: ゼロ除算だ。何やってんだ。
例外クラスのよく使われるメソッド
- getMessage(): 例外のメッセージを取得
throw new Exception("ゼロ除算だ。何やってんだ。");
// ↑ でメッセージを設定している
- getCode(): 例外に関連付けられたコードを取得
- getFile(): 例外が発生したファイル名を取得
- getLine(): 例外が発生した行番号を取得
- getTrace(): バックトレース情報を配列で取得
- getTraceAsString(): バックトレース情報を文字列で取得
getTraceAsString()の例
<?php
function divide($a, $b) {
if ($b === 0) {
throw new Exception("ゼロ除算だ。何やってんだ。");
}
return $a / $b;
}
try {
divide(10, 0);
} catch (Exception $e) {
echo $e->getTraceAsString();
}
実行結果
#0 /workspace/Main.php(11): divide()
#1 {main}
補足
#0 は例外がスローされたメソッド(divide)とスローされた行数(11)を示しています。 #1 mainはdivide()メソッドの実行された場所がどの関数内でもなく、トップレベル で実行されたことを示しています。