通常の実行時 (try ブロック内で例外が投げられなかった 場合) は、catch ブロック内は処理されず、それ以降から処理が続けられます。
try-catchの使い方について、例を挙げて解説させていただきます。
try-catch
try-catchブロックの役割
通常は、BLOCK1でtry-catch処理に必要な変数定義などの準備処理を入れます。
BLOCK2、つまりtryブロック。メイン処理に必要なロジックを入れて実行する。
BLOCK3、即ち、catchブロック。メイン処理に何が例外が発生したら、その情報が捕まれて、何かの対策にして、エンドユーザーに分かりやすくように、またはその情報を用いてログ出力して、開発者に原因調査に調べやすいように異常処理を入れます。
BLOCK4、tryブロックまたはcatchブロックの処理が終わったら、後続処理として実行する。ただ、状況により後続ロジックを処理しない場合があります。
/**
* BLOCK1
* try-catchの前に何かのロジック処理
*
**/
try {
// try start
/**
* BLOCK2
* tryロジック処理
*
**/
// try end
} catch ( Exception $ex ) {
// catch start
/**
* BLOCK3
* catchロジック処理
*
**/
// catch end
}
/**
* BLOCK4
* try-catchの後に何かのロジック処理
**/
サンプルから説明
例え、ピープルというテーブルに一行インサートして、何が発生したら、そのエラー情報をキャッチしてログに出力する処理を実装しましょう。
上記のブロックの役割を参考にして、単純に 例1-①
の書き方でいいではないでしょうか。
/* 例1-① */
$PeopleModel = new PeopleInfoModel();
try {
$insert = $PeopleModel->insertOneRecord ( $conn, $pno, $pname, $mail, $address);
// 後続処理が続く
} catch ( Exception $ex ) {
LogUtil::logError ( Const::DEF_LOG_DATABASE, $ex->getMessage () );
// 後続処理が続く
}
// 後続処理
後続処理中断
ただし、システム内にエラーが発生しているのに、後続処理が続くのはまずくない?
継続処理すると、後ろの処理が全部通ってしまい、途中でエラーが発生しても、最後まで正常終了となる場合があります。
API系やBatch系で、途中で何かしらのエラーが起こしたら、その場で処理が止まって、エラーで返却するのほうが多いです。
/* 例1-② */
$PeopleModel = new PeopleInfoModel();
try {
$insert = $PeopleModel->insertOneRecord ( $conn, $pno, $pname, $mail, $address);
// 後続処理が続く
} catch ( Exception $ex ) {
return FALSE;
// 後続処理は中断
}
// 後続処理
追跡ログ出力
catch自身はエラー情報が$ex
に揃えているが、ログ出力処理がないと、自動的に出せないので、$ex->getMessage ()
を用いて、ちゃんとエラー情報を明確的に出しましょう。
そしたら、原因調査や追跡が楽になるでしょう。
/* 例1-③ */
$PeopleModel = new PeopleInfoModel();
$insert = FALSE;
try {
$insert = $PeopleModel->insertOneRecord ( $conn, $pno, $pname, $mail, $address);
// 後続処理が続く
} catch ( Exception $ex ) {
LogUtil::logError ( Const::DEF_LOG_DATABASE, $ex->getMessage () );
return FALSE;
// DBエラーログを出力して、後続処理は中断
}
// 後続処理
Tip
繰り返し文にtry-catchがある場合、何がのエラーが起こしたら、returnではなくて、繰り返し処理を継続するのかを決めてから、breakやcontinueを用って制御しましょう。
処理パターンのこだわり
上記は、主にcatchブロックの説明ですが、tryブロックだとそれだけで十分ではありません。
なぜなら、$insert
は初期値の定義があるが、tryブロックでの実行結果はTRUE
で返却されるのははっきりできないので、もしもFALSE
のままでしたら、tryブロックで正常として終了してしまい、また後続処理が続くことになります。
だから、tryブロックで厳密に$insert
の実行結果をチェックして、処理継続するかを決まります。
/* 例2-① */
$PeopleModel = new PeopleInfoModel();
$insert = FALSE;
try {
$insert = $PeopleModel->insertOneRecord ( $conn, $pno, $pname, $mail, $address);
if (!$insert) {
LogUtil::logError ( Const::DEF_LOG_DATABASE, "テーブル登録失敗 pno[" . $pno . "]" );
return FALSE;
// DBエラーログを出力して、後続処理は中断
}
// 後続処理が続く
} catch ( Exception $ex ) {
LogUtil::logError ( Const::DEF_LOG_DATABASE, $ex->getMessage () );
return FALSE;
// DBエラーログを出力して、後続処理は中断
}
// 後続処理
わざわざtryブロックとcatchブロックの中で実行結果チェック処理を2回で書くのはめんどくさいと思っている人にとって、もっと簡潔に書くと、継続処理の制御をまとめていいではないか。
/* 例2-② */
$PeopleModel = new PeopleInfoModel();
$insert = FALSE;
try {
$insert = $PeopleModel->insertOneRecord ( $conn, $pno, $pname, $mail, $address);
} catch ( Exception $ex ) {
LogUtil::logError ( Const::DEF_LOG_DATABASE, $ex->getMessage () );
}
if (!$insert) {
LogUtil::logError ( Const::DEF_LOG_DATABASE, "テーブル登録失敗 pno[" . $pno . "]" );
return FALSE;
// DBエラーログを出力して、後続処理は中断
}
// 後続処理
Tip
PHPは厳密な言語ではないので、自由に楽に書いていいと思い込んでしまったら、いつのタイミングでそれの弱点によるシステム障害が発生したら、大変な事になってしまいます。
いいコーディング習慣を身に付けるのはいつでも違いない。
参考:
例外(exceptions)
---I Love PHP (。・ω・。)ノ♡