PHPにおけるtry-catch文(例外処理)の使い方を解説します
try-catch は PHP のエラーハンドリングの基本となる構文で、放っておくとプログラムを異常終了させてしまう「例外(Exception)」を捕まえて、処理を安全に続けるために利用します。本記事では、PHP における try-catch の使い方を、PHP 初心者の方向けに解説します。はじめに
try-catch は、プログラミングにおけるエラーハンドリングの重要な手段のひとつです。
異常発生により処理が継続できなくなることを防ぐため、本来であれば終了してしまうプログラムの「例外」を制御するために try-catch を利用します。
本記事では、PHP における try-catch の使い方を、初心者の方向けに解説します。
※本記事は PHP 8.x を想定しています。
try-catch の基本的な使い方
PHP での try-catch の基本形は次の通りです。
try {
// 例外が発生する可能性のあるコード
} catch (Exception $e) {
// 例外が発生した場合に行う処理
}
もう少しイメージを掴むために、簡単なサンプルコードを見てみましょう。
下記は、渡された値が空でないかを判定し、空の場合には例外を投げるコードです。
$name = "";
echo "処理を開始します。<br>";
try {
if ($name === "") {
throw new Exception("名前が入力されていません。");
}
echo "こんにちは、{$name}さん<br>";
} catch (Exception $e) {
echo $e->getMessage() . "<br>";
}
echo "処理を終了します。";
実行結果は、
処理を開始します。
名前が入力されていません。
処理を終了します。
となります。throw new Exception(...) で自分の好きなメッセージを持った例外を発生させ、それを catch ブロックで受け取っています。もし try-catch がなかった場合、例外が発生した時点で処理が終了してしまいます。
$name = "";
echo "処理を開始します。<br>";
if ($name === "") {
throw new Exception("名前が入力されていません。"); // ここで処理が強制終了する
}
echo "こんにちは、{$name}さん<br>";
try-catch の便利な使い方
エラーメッセージをカスタマイズする
先ほどの例のように、事前に例外が予測できる場面では自分で throw することでメッセージをコントロールできます。
入力値のチェックなど、条件で処理を分けて例外を投げるパターンは実務でよく使います。
function checkAge(int $age): void
{
if ($age < 0) {
throw new Exception("年齢に負の値は指定できません。");
}
if ($age >= 150) {
throw new Exception("年齢の値が大きすぎます。");
}
echo "年齢は {$age} 歳です。<br>";
}
try {
checkAge(-1);
} catch (Exception $e) {
echo $e->getMessage() . "<br>";
}
実行結果:
年齢に負の値は指定できません。
処理を終了させる
ここまでは catch した後で処理を続行させるコードでしたが、原因追跡のためのログを出力した上で、処理を中止させたい場面もよくあります。
$name = "";
echo "処理を開始します。<br>";
try {
if ($name === "") {
throw new Exception("名前が入力されていません。処理を中止します。");
}
echo "こんにちは、{$name}さん<br>";
} catch (Exception $e) {
error_log($e->getMessage()); // サーバのエラーログに記録
echo $e->getMessage() . "<br>";
exit();
}
echo "処理を終了します。"; // ← ここは実行されない
実行結果:
処理を開始します。
名前が入力されていません。処理を中止します。
try-catch をネストさせる
try-catch は入れ子(ネスト)にすることも可能です。
例として、入力を検証したうえで json_decode で JSON をパースし、それぞれの段階で例外を扱ってみましょう。
(json_decode に JSON_THROW_ON_ERROR フラグを渡すと、パース失敗時に JsonException という例外を投げてくれます。)
$input = '{"name": "Alice",'; // 途中で切れた不正な JSON
echo "処理を開始します。<br>";
try {
if ($input === "") {
throw new Exception("入力が空です。");
}
try {
$data = json_decode($input, associative: true, flags: JSON_THROW_ON_ERROR);
echo "name: {$data['name']}<br>";
} catch (JsonException $e) {
echo "JSON の解析に失敗しました: " . $e->getMessage() . "<br>";
throw new Exception("入力を処理できませんでした。");
}
} catch (Exception $e) {
echo $e->getMessage() . "<br>";
}
実行結果:
処理を開始します。
JSON の解析に失敗しました: Syntax error
入力を処理できませんでした。
内側の catch で JsonException を受け取ってメッセージを出し、その後さらに外側に伝えたい場合は再度 throw して外側の catch で拾えるようにできます。
入れ子は便利ですが、深くなりすぎると読みにくくなるので、必要な範囲だけに留めましょう。
finally 節:必ず実行される処理を書く
成功/失敗にかかわらず必ず実行したい後処理(データベースの接続を閉じる、ロックを解放するなど)は finally ブロックに書きます。
echo "処理を開始します。<br>";
try {
throw new Exception("何らかのエラー");
} catch (Exception $e) {
echo "catch: " . $e->getMessage() . "<br>";
} finally {
echo "finally: 後片付けを実行しました。<br>";
}
echo "処理を終了します。";
実行結果:
処理を開始します。
catch: 何らかのエラー
finally: 後片付けを実行しました。
処理を終了します。
try や catch の中で return や exit しても、finally は必ず実行されます。
PHP が標準で用意している例外
これまでは Exception を自分で new して throw していましたが、PHP には最初からたくさんの例外クラスが用意されています。ライブラリや標準関数を呼び出すときに、これらの例外が飛んでくることがあります。
JsonException:json_decode/json_encodeにJSON_THROW_ON_ERRORを付けて失敗したとき。PDOException:PDOでデータベースに接続できなかった、SQL が実行できなかったときなど。InvalidArgumentException: 引数の値がおかしいときに投げる想定の例外。RuntimeException: 実行時に起こりうる一般的なエラー用。
いずれも Exception の仲間なので、catch (Exception $e) でまとめて捕まえることができます。
PHP 8 で気をつけたい点:ゼロ除算
ひとつだけ、初心者がハマりやすい落とし穴を紹介しておきます。
PHP 8.0 以降、10 / 0 のようなゼロ除算を実行すると、DivisionByZeroError という例外が投げられます。
ただし、この DivisionByZeroError は ここまで扱ってきた Exception の仲間ではなく、Error の仲間です。そのため catch (Exception $e) では捕まえられません。
try {
$result = 10 / 0;
} catch (Exception $e) {
echo "捕まえた: " . $e->getMessage(); // ← 実行されない
}
// 未捕捉のまま Uncaught DivisionByZeroError で終了する
Error の仲間は「プログラム側のロジックミス」を表すもので、原則として catch で処理するのではなく、そもそも発生させないように事前チェックするのが基本です。
if ($number === 0) {
throw new Exception("0 では割れません。");
}
$result = 10 / $number;
「割る前に 0 じゃないか確認する」ように書くことで、そもそも DivisionByZeroError が発生する状況を防げます。
catch は「起こりうる想定外を安全に受け止める」ためのもの、事前チェックは「そもそも起きないようにする」ためのもの、と役割を分けて考えるとスッキリします。
まとめ
いかがでしたでしょうか?
PHP の try-catch は、システムを構築していく上で必ず必要になる処理です。
- まず
tryブロックに例外が起こりうる処理を書く catch (Exception $e)でその例外を受け取り、メッセージを出したりログに残したりする- 後片付けが必要なら
finallyで確実に実行する - ネストは必要な範囲だけに留める
- ゼロ除算のような「プログラムミス由来のエラー」は catch するより、事前チェックで防ぐ
この基本を押さえておけば、あとは実際にコードを書きながら、標準の JsonException や PDOException など、状況に応じた例外の使い方を覚えていくことができます。ぜひこの機会にマスターしていきましょう。













