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('独自例外!');
?>
ベースクラスの補足
catch
でException
を指定すると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
という最終的な処理を記述するブロックを付けることができます。
finally
はtry
文内で例外が発生する&しないに関わらず実行されます。
<?php
try {
throw new Exception('例外発生!');
} catch (Exception $e) {
echo $e->getMessage(), "\n";
} finally {
echo "終わりました。\n";
}
?>
実行結果。
例外発生!
終わりました。
↓のようにthrow
が発生しなくても実行されます。
<?php
try {
// なにもしない
} finally {
echo "終わりました。\n";
}
?>
実行結果。
終わりました。
finallyとreturn文
finally
はreturn
文が実行された場合も呼ばれます。
<?php
function func() {
try {
return 1;
} finally {
echo "終わりました。\n";
}
}
echo func(), "\n";
?>
実行結果。
終わりました。
1
finally
にreturn
文がある場合はそちらの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の例外クラスはどのクラスから派生させるべきか答えよ
- Error
- Exception
- Invalid
Q2: 例外処理で最終的に実行したい処理を記述するブロックを答えよ
- try
- catch
- finally
Q3: catch
ブロックで複数の例外をまとめたいときに使われる記号を答えよ
- &
- |
正解
Q1: 2
Q2: 3
Q3: 2