try~catch文の構造PHPのtry~catch文は↓のような構造を持ちます。try{処理}catch(例外クラス名変数){例外処理}またはtry{処理}catch(例外クラ..." /> PHPのtry~catch文(例外処理)の簡単な使い方

ユーニックス総合研究所

  • home
  • archives
  • php-try-catch

PHPのtry~catch文(例外処理)の簡単な使い方

  • 作成日: 2020-08-28
  • 更新日: 2023-12-24
  • カテゴリ: PHP

PHPの例外処理の書き方

PHPにはtry~catch文という例外を扱う文があります。
これを使うとPHPで例外を使ったエラーハンドリングが可能になります。

例外は例えば↓のように使います。

<?php  

try {  
    throw new Exception('例外発生!');  
} catch (Exception $e) {  
    echo $e->getMessage(), "\n";  
}  

?>  

try~catch文の構造

PHPのtry~catch文は↓のような構造を持ちます。

try {  
    処理  
} catch (例外クラス名 変数) {  
    例外処理  
}  

または  


try {  
    処理  
} catch (例外クラス名 変数) {  
    例外処理  
} catch (例外クラス名 変数) {  
    例外処理  
}  

または  

try {  
    処理  
} catch (例外クラス名 変数) {  
    例外処理  
} finally {  
    最終処理  
}  

まず例外が発生するであろう処理をtry文で囲みます。
「例外が発生する」というのはthrow文が実行されるということです。

そしてそのtry文にcatchを付けることでtry文内で発生した例外を補足することができます。
try文で最終的に必ず実行させたい処理を書きたい場合はtry文にfinallyをつけます。

例外の使い道

例外はいつ使うのでしょうか?
例外が実装されている言語ではエラーハンドリングに例外を使うのが一般的です。
エラーハンドリングというのは「エラーが発生した時の振る舞い方の定義」です。

エラーが発生したらthrow文で例外クラスのインスタンスを投げます。
そしてその例外はtry文のcatchで補足されます。
あとはこのcatch内でそのエラーに対する処理を行います。
これが一般的な例外処理です。

throwした例外をcatchする

エラーが発生した場合、例外をthrowしますが、このthrowされた例外はtry文のcatchで補足されます。

<?php  

try {  
    // ここで例外が発生する  
    throw new Exception('例外発生!');  
} catch (Exception $e) {  
    // ここで例外を補足する  
    echo $e->getMessage(), "\n";  
}  

?>  

実行内容。

例外発生!  

throwには例外クラスのインスタンスをnewで渡します。
コンストラクタには例外内容を表す文字列('例外発生!')を指定できます。

その例外はthrowされ、処理を飛び越えてcatchにやってきます。
catchには補足する例外クラスを指定します。
↑の場合はExceptionクラスを補足したいのでcatch (Exception $e)としています。
catch (Exception $e)$eにはthrowされた例外クラスのインスタンスが渡されます。

このExceptionクラスはgetMessageというエラー内容を表示するメソッドを持っています。
↑の場合、echoで表示されるエラー内容は例外発生!になります。

catchは複数書き連ねることができます。

処理を飛び越える例外の挙動

throwされた例外はあらゆる処理を飛び越えていきます。
さながら流れ星のようです。

throwされた例外は、try文で補足されない場合は最終的にコンソール画面に例外が発生した旨のエラーメッセージを表示します。

throw new Exception('例外発生!');  

出力結果。

PHP Fatal error:  Uncaught Exception: 例外発生! in sample.php:3  
Stack trace:  
#0 {main}  
  thrown in sample.php on line 3  

これは関数などの深度の深いレイヤーでも同じです。
たとえば↓は関数が複数呼ばれていますが、例外はそれらの関数を飛び越えて画面にエラーを表示します。

<?php  

function b() {  
    throw new Exception('例外発生!');  
}  

function a() {  
    b();  
}  

a();  

?>  

出力結果。

PHP Fatal error:  Uncaught Exception: 例外発生! in sample.php:4  
Stack trace:  
#0 sample.php(8): b()  
#1 sample.php(11): a()  
#2 {main}  
  thrown in sample.php on line 4  

Exceptionクラス

スローされる例外クラスはExceptionクラスあるいはExceptionクラスを継承したクラスでなければいけません。
それ以外のオブジェクトをスローしようとするとエラーになります。

Exception  

独自例外

独自の例外クラスを作りたい場合はExceptionクラスを継承します。

<?php  

class MyException extends Exception {  
}  

throw new MyException('独自例外!');  

?>  

ベースクラスの補足

catchExceptionを指定するとExceptionを継承したクラスをすべて補足するようになります。

<?php  

class MyException extends Exception {  
}  

try {  
    throw new MyException('例外発生!');  
} catch (Exception $e) {  
    echo $e->getMessage(), "\n";  
}  

?>  
例外発生!  

これはExceptionがすべての例外クラスのベースだからです。
つまり、ベースとなるクラスを指定すれば、その派生クラスをまとめて補足できるようになります。

<?php  

class MyBase extends Exception {  
}  

class MyException extends MyBase {  
}  

try {  
    throw new MyException('例外発生!');  
} catch (MyBase $e) {  
    echo $e->getMessage(), "\n";  
}  

?>  
例外発生!  

複数の例外をcatchする

複数の例外をcatchしたい場合はcatchを必要数書き足します。

<?php  

class Error1 extends Exception {  
}  

class Error2 extends Exception {  
}  

try {  
    throw new Error2('例外発生!');  
} catch (Error1 $e) {  
    echo 'Error1: ', $e->getMessage(), "\n";  
} catch (Error2 $e) {  
    echo 'Error2: ', $e->getMessage(), "\n";  
}  

?>  

出力結果。

Error2: 例外発生!  

複数の例外を1つのcatchにまとめる

catchで補足する複数の例外は|でまとめることができます。

<?php  

class MyException extends Exception {  
}  

try {  
    throw new MyException('独自例外!');  
} catch (Exception | MyException $e) {  
    echo get_class($e), "\n";  
}  

?>  

出力結果。

MyException  

↑の場合、ExceptionまたはMyExceptionのインスタンスは$eに渡されます。

finallyの挙動

try文にはfinallyという最終的な処理を記述するブロックを付けることができます。
finallytry文内で例外が発生する&しないに関わらず実行されます。

<?php  

try {  
    throw new Exception('例外発生!');  
} catch (Exception $e) {  
    echo $e->getMessage(), "\n";  
} finally {  
    echo "終わりました。\n";  
}  

?>  

実行結果。

例外発生!  
終わりました。  

↓のようにthrowが発生しなくても実行されます。

<?php  

try {  
    // なにもしない  
} finally {  
    echo "終わりました。\n";  
}  

?>  

実行結果。

終わりました。  

finallyとreturn文

finallyreturn文が実行された場合も呼ばれます。

<?php  

function func() {  
    try {  
        return 1;  
    } finally {  
        echo "終わりました。\n";  
    }  
}  

echo func(), "\n";  

?>  

実行結果。

終わりました。  
1  

finallyreturn文がある場合はそちらのreturn文が最終的に実行されます。

<?php  

function func() {  
    try {  
        return 1;  
    } finally {  
        return 2;  
    }  
}  

echo func(), "\n";  

?>  

実行結果。

2  

使用例

try~catch文の使用例です。

0除算エラー

0除算エラーのエラーハンドリング例です。

<?php  

class ZeroDivisionError extends Exception {  
}  

function div($a, $b) {  
    if ($b === 0) {  
        throw new ZeroDivisionError('0除算エラー');  
    }  

    return $a / $b;  
}  

try {  
    echo div(4, 2), "\n";  
    echo div(4, 0), "\n";  
} catch (ZeroDivisionError $e) {  
    echo $e->getMessage(), "\n";  
}  

?>  
2  
0除算エラー  

問題

Q1: PHPの例外クラスはどのクラスから派生させるべきか答えよ

  1. Error
  2. Exception
  3. Invalid

Q2: 例外処理で最終的に実行したい処理を記述するブロックを答えよ

  1. try
  2. catch
  3. finally

Q3: catchブロックで複数の例外をまとめたいときに使われる記号を答えよ

  1. &
  2. |

正解

Q1: 2
Q2: 3
Q3: 2