PHP
 Computer >> コンピューター >  >> プログラミング >> PHP

PHPの例外処理:複数のcatchブロックで例外の種類別に処理を分ける方法

はじめに

PHPでは、tryブロックの後に複数のcatchブロックを連ねることで、発生した例外の種類に応じて異なる処理を実行できます。これにより、DivisionByZeroErrorTypeError のような組み込みのエラーから、開発者が独自に定義した例外クラスまで、柔軟かつきめ細かにハンドリングすることが可能です。

複数のcatchブロックの仕組み

tryブロック内で例外がスローされると、PHPは上から順にcatchブロックをチェックし、最初に型が一致したブロックだけを実行します。そのため、具体的な例外型ほど上に、Exception のような汎用的な例外型ほど下に配置するのが基本の書き方です。

サンプルコード

次の例では、DivisionByZeroErrorTypeErrorArgumentCountErrorInvalidArgumentException の4種類の条件をそれぞれ専用のcatchブロックで処理し、さらにどれにも該当しない例外を受け取る汎用のcatchブロックも用意しています。

<?php
declare(strict_types=1);
function divide(int $a, int $b) : int {
    return $a / $b;
}
$a=10;
$b=0;
try {
    if (!$b) {
        throw new DivisionByZeroError('Division by zero.');
    }
    if (is_int($a)==FALSE || is_int($b)==FALSE) {
        throw new InvalidArgumentException("Invalid type of arguments");
    }
    $result=divide($a, $b);
    echo $result;
}
catch (TypeError $x) { // 引数の型が一致しない場合
    echo $x->getMessage();
}
catch (DivisionByZeroError $y) { // 分母が0の場合
    echo $y->getMessage();
}
catch (ArgumentCountError $z) { // 引数の数が2個でない場合
    echo $z->getMessage();
}
catch (InvalidArgumentException $i) { // 引数の型が不正な場合
    echo $i->getMessage();
}
catch (Exception $ex) { // その他の未捕捉の例外
    echo $ex->getMessage();
}
?>

実行結果

1. 分母が0の場合

$b が 0 のため、0による除算のエラーメッセージが表示されます。

Division by 0

2. 戻り値の型が不一致の場合

$b=3 に変更すると、divide関数は整数(int)の戻り値を期待している一方で、除算結果が浮動小数点数(float)になるため TypeError が発生します。

Return value of divide() must be of the type integer, float returned

3. 引数の数が不足している場合

$res=divide($a); のように引数を1つだけで呼び出すように変更すると、ArgumentCountError が発生します。

Too few arguments to function divide(), 1 passed in C:\xampp\php\test1.php on line 13 and exactly 2 expected

4. 引数の型が不正な場合

引数のいずれかが整数でない場合は、InvalidArgumentException のケースに該当します。

Invalid type of arguments

補足:マルチキャッチ構文(PHP 7.1以降)

PHP 7.1以降では、パイプ記号(|)を使って複数の例外型を1つのcatchブロックでまとめて受け取ることができます。同じ処理でよい例外をグループ化したい場合に便利です。

catch (TypeError | ArgumentCountError $e) {
    echo $e->getMessage();
}

まとめ

  • catchブロックは上から順に評価され、最初に一致した1つだけが実行される
  • 具体的な例外型を上に、汎用的な例外型(Exception など)を下に配置する
  • PHP 7.1以降は | によるマルチキャッチ構文でコードを簡潔にできる
  • PHP 7以降の ErrorException の両方をまとめて捕捉したい場合は、共通インターフェースである Throwable を指定すると確実
  1. Javaのtry-catchによる例外処理の基本とfinallyの使い方を徹底解説

    どんなに優れたプログラマーでも、コードにミスを犯すことはあります。タイプミス、予期しないユーザー入力、追跡が難しいさまざまな要因によって、エラーは発生します。 そこで活躍するのが「例外処理」です。質の高いコードには例外ハンドラーが組み込まれており、エラーが発生した際にあらかじめ定義された方法で対応できるようになっています。例外ハンドラーは、プログラムがエラーに遭遇したときにどう振る舞うべきかを指示してくれるため、非常に有用です。 Javaでは、try...catchブロックを使って例外処理を行います。この記事では、例外処理の基礎知識から、try...catchブロックを使った例外の処理方法、さ

  2. C++の例外処理入門!try・catch・throwの基本と標準例外クラス一覧

    C++における例外処理(Exception Handling)とは、プログラムの実行時に発生するエラー(ランタイムエラー)を適切に扱うための仕組みです。例外とは、実行時に送出(スロー)されるイベントのことで、C++ではすべての標準例外が std::exception クラスから派生しています。もし例外を捕捉しなかった場合、例外メッセージが出力され、プログラムは強制終了してしまいます。 C++標準では、例外関連のクラスが <exception> ヘッダに定義されており、プログラムの中で自由に利用できます。親子関係によるクラス階層は次のようになっています。 C++の主な標準例外クラス