はじめに
例外処理を行う際、同じような種類の例外をひとまとめにキャッチしたいことがあります。PHP7.1以降では、catch
ブロックに「パイプ記号(|)」を使うことで、複数の例外をまとめて処理できるようになりました。今回はこの複合キャッチの仕組みを、出力結果を確認しながら理解していきましょう。
目次
🧩 サンプルコード
<?php
declare(strict_types=1);
error_reporting(-1);
class HogeException extends RuntimeException {}
class FooException extends RuntimeException {}
class BarException extends RuntimeException {}
try {
throw new BarException("any bar exception");
} catch (HogeException | FooException $e) {
echo "HogeException | FooException\n";
echo $e->getMessage(), "\n";
} catch (BarException $e) {
echo "BarException\n";
echo $e->getMessage(), "\n";
}
💡 出力結果
BarException
any bar exception
この結果は 正解 です。なぜこのようになるのか、順を追って見てみましょう。
🧠 処理の流れ(図解)
try
ブロックで発生した例外は、上から順に catch
ブロックにマッチしていきます。
┌────────────┐
│ try { ... }│
└─────┬──────┘
│
▼
throw new BarException
│
┌─────────────┴────────────────┐
│ │
▼ ▼
catch(HogeException|FooException) ❌一致せずスルー
catch(BarException) ✅一致して実行!
throw new BarException() に対して、最初の catch(HogeException | FooException) には一致しません。そのためスキップされ、次の catch(BarException) が実行されます。
🧩 パイプ(|)でまとめられる条件
複数の例外をまとめたい場合は、それらのクラスが 同じ階層(継承関係にない) でもOKです。
ただし、まとめて指定した場合 $e
の型は 共通の親クラス型 として扱われます。
catch (HogeException | FooException | BarException $e) {
echo "まとめてキャッチ";
}
このように書くと、どの例外でも同じ処理を実行できます。出力は以下のようになります👇
まとめてキャッチ
⚠️ 注意ポイント
注意点 | 説明 |
---|---|
catchは上から評価される | 上に書かれたcatchにマッチした時点で下は評価されない |
パイプ指定に含まれない例外はスルーされる | 次のcatchがなければ未処理例外になる |
$e の型が曖昧になる | 複数例外をまとめると、具体的な型チェックがしにくくなる |
まとめ
投げられた例外 | catch句の指定 | 実行されるcatch | 出力 |
---|---|---|---|
HogeException | HogeException | FooException | 1つ目 | HogeException | FooException |
FooException | HogeException | FooException | 1つ目 | HogeException | FooException |
BarException | HogeException | FooException, BarException | 2つ目 | BarException |
🧭 まとめのポイント
|
(パイプ)で複数の例外をまとめて処理できる- 上から順にマッチするcatchが実行される
- 含まれない例外はスルーされる(未処理注意)
- 共通の処理をまとめたいときに便利