LoginSignup
96
107

More than 5 years have passed since last update.

【PHP】try-catch解説

Last updated at Posted at 2018-05-22

通常の実行時 (try ブロック内で例外が投げられなかった 場合) は、catch ブロック内は処理されず、それ以降から処理が続けられます。
try-catchの使い方について、例を挙げて解説させていただきます。

try-catch

try-catchブロックの役割

通常は、BLOCK1でtry-catch処理に必要な変数定義などの準備処理を入れます。
BLOCK2、つまりtryブロック。メイン処理に必要なロジックを入れて実行する。
BLOCK3、即ち、catchブロック。メイン処理に何が例外が発生したら、その情報が捕まれて、何かの対策にして、エンドユーザーに分かりやすくように、またはその情報を用いてログ出力して、開発者に原因調査に調べやすいように異常処理を入れます。
BLOCK4、tryブロックまたはcatchブロックの処理が終わったら、後続処理として実行する。ただ、状況により後続ロジックを処理しない場合があります。

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-①
/* 例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-②
/* 例1-② */
$PeopleModel = new PeopleInfoModel();
try {
    $insert = $PeopleModel->insertOneRecord ( $conn, $pno, $pname, $mail, $address);
    // 後続処理が続く
} catch ( Exception $ex ) {
    return FALSE;
    // 後続処理は中断
}
// 後続処理

追跡ログ出力

catch自身はエラー情報が$exに揃えているが、ログ出力処理がないと、自動的に出せないので、$ex->getMessage ()を用いて、ちゃんとエラー情報を明確的に出しましょう。
そしたら、原因調査や追跡が楽になるでしょう。

例1-③
/* 例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-①
/* 例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-②
/* 例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 (。・ω・。)ノ♡

96
107
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
96
107