# ch04 — 複数の catch ブロック

Source: https://php-school.pages.dev/topics/exception/ch04-multi-catch/
Site: AIと学ぶPHPの学校 (https://php-school.pages.dev)
Lesson: 例外処理
Level: L3

Reference (official): https://www.php.net/manual/ja/language.exceptions.php

## 本文

# ch04 — 複数の catch ブロック

## 概要

実際のアプリでは、「入力値が変」「ファイルが読めない」「DB が落ちている」といった **種類の違うエラー** が同じ try ブロックの中で起こり得る。すべてを一律 `catch (Exception $e)` で受けると、画面に出すべきメッセージも対応方針も同じになってしまい、適切なリカバリができない。

PHP では `catch` ブロックを **複数並べる** ことで、例外の **型ごとに分岐** できる。上から順にマッチ判定され、最初に該当した catch だけが実行される。`InvalidArgumentException` (引数の値が不正) なら入力フォームに戻す、`RuntimeException` (実行時の外部要因) なら再試行を促す、という分け方ができる。継承関係があるので、子クラスをより上の catch に書く順番が重要。

PHP 8 からは **`catch (TypeA | TypeB $e)`** と書いて、複数型を 1 つの catch で同時に受けることもできる。同じ処理で良いエラーを束ねたいときに使う。この章では、標準ライブラリに用意された `InvalidArgumentException` / `RuntimeException` を投げ分けて、catch でどう拾い分けるかをドリルで体感する。

## 学習目標

- `catch` を **複数並べる** ことで、例外の種類ごとに処理を分けられる
- 上から順にマッチ判定され、最初に合った catch だけが実行される
- `InvalidArgumentException` `RuntimeException` など標準例外の存在を知る

## 所要時間

スライド 5 分 + ドリル 1 問 = **12 分**

## ドリル

| no | 内容 |
|---|---|
| 01 | `InvalidArgumentException` と `RuntimeException` を別 catch で受ける |

## スライド

---
marp: true
theme: dojo
paginate: true
size: 16:9
---

<!--
LLM_CONTEXT:
  Lesson 10 / Chapter 4
  目的: 例外の種類ごとに catch を分け、種類別の処理を書く
  扱わない: union catch (catch (A|B $e)) は学習負荷で割愛 / finally (ch05) / カスタム例外 (ch06)
  読み上げ時間目安: 4 分半〜5 分
-->

# 複数の catch ブロック

Lesson 10 / Chapter 4

---

## 例外には種類がある

```php
<?php
throw new Exception(...);                  // 一般的な例外
throw new InvalidArgumentException(...);   // 引数がおかしい
throw new RuntimeException(...);           // 実行時の問題
```

- PHP には **標準で複数の例外クラス** が用意されている
- 種類によって対応も変えたい
  - 引数エラー → ユーザーに「入力を直して」
  - 実行時エラー → ログを残して再試行

---

## `catch` を複数並べる

```php
<?php
try {
    // 失敗するかもしれない処理
} catch (InvalidArgumentException $e) {
    echo "引数エラー: " . $e->getMessage() . "\n";
} catch (RuntimeException $e) {
    echo "実行時エラー: " . $e->getMessage() . "\n";
}
```

- `catch` をいくつでも並べられる
- 投げられた例外の **型** で振り分けられる

---

## マッチは「上から順に」

```php
<?php
try {
    throw new InvalidArgumentException("負の値");
} catch (InvalidArgumentException $e) {
    echo "引数: " . $e->getMessage() . "\n";   // ← ここに来る
} catch (RuntimeException $e) {
    echo "実行時: " . $e->getMessage() . "\n";
}
```

実行結果:

```
引数: 負の値
```

- 上から順にチェック、最初に合った catch だけが走る
- 残りは無視される

---

## 別の例外を投げると別の catch に行く

```php
<?php
try {
    throw new RuntimeException("DB 接続失敗");
} catch (InvalidArgumentException $e) {
    echo "引数: " . $e->getMessage() . "\n";
} catch (RuntimeException $e) {
    echo "実行時: " . $e->getMessage() . "\n";   // ← ここに来る
}
```

実行結果:

```
実行時: DB 接続失敗
```

- 投げた例外の型に応じて、自動で正しい catch が選ばれる

---

## このチャプターでできるようになること

✅ `catch` を複数並べられる
✅ 例外の種類ごとに違う処理を書ける
✅ `InvalidArgumentException` `RuntimeException` を区別できる
✅ catch は上から順にマッチすると知っている

→ ドリルへ
