PHPの例外スロー(throw)徹底解説!ErrorとExceptionの基本からSPL例外まで
はじめに
PHPでは、ThrowableインターフェースがErrorクラスとExceptionクラスによって実装されています。すべての定義済みErrorクラスはErrorクラスを継承しており、tryブロック内で対応する例外インスタンスが投げられると、適切なcatchブロックで処理されます。
この仕組みにより、予期しないエラーが発生した場合でもプログラムを強制終了させず、柔軟にエラーハンドリングを行うことが可能になります。
例外のスロー(throw)の基本動作
tryブロック内で例外が発生しなかった場合、プログラムは最後のcatchブロックの後に定義されたコードからそのまま実行を継続します。一方、例外が投げられた場合は制御がcatchブロックへ移り、エラー処理を実行した後もスクリプト自体は引き続き動作します。
サンプル:Exceptionをスローしてキャッチする
以下の例では、ゼロ除算が発生しようとしたタイミングでExceptionをthrowし、catchブロックでメッセージを表示しています。
<?php
function div($x, $y) {
if (!$y) {
throw new Exception('Division by zero.');
}
return $x/$y;
}
try {
echo div(10,5) . "\n";
echo div(10,0) . "\n";
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "\n";
}
// 処理はここから継続
echo "Execution continues\n";
?>
出力結果
2 Caught exception: Division by zero. Execution continues
注目すべきは、例外を捕捉した後も「Execution continues」が出力されている点です。つまり、例外処理を適切に行えば、エラー発生後もプログラムの実行を止めることなく継続できるのです。
サンプル:TypeErrorをキャッチする
次の例では、関数に想定外の型の引数が渡されたため、実行時にTypeErrorがスローされます。これにより、対応するエラーメッセージが表示されます。
<?php
function add(int $num1, int $num2){
return $num1 + $num2;
}
try {
$value = add(1, 'one');
} catch (TypeError $e) {
echo $e->getMessage(). "\n";
}
?>
出力結果
Argument 2 passed to add() must be of the type integer, string given
型宣言を持つ関数に不正な型の値を渡すと、PHPは自動的にTypeErrorをスローします。このように、throw文を使わなくてもPHP内部で例外が発生するケースがあることを覚えておきましょう。
SPL定義済み例外の一覧
標準PHPライブラリ(SPL)には、目的別にあらかじめ定義された例外クラスが多数用意されています。代表的な例外は以下の通りです。
| LogicException | プログラムのロジックにおけるエラーを表す例外。 |
| BadFunctionCallException | コールバックが未定義の関数を参照している場合や、引数が不足している場合にスローされる例外。 |
| BadMethodCallException | コールバックが未定義のメソッドを参照している場合や、引数が不足している場合にスローされる例外。 |
| DomainException | 値が定義済みの有効なデータドメインに従っていない場合にスローされる例外。 |
| InvalidArgumentException | 引数が期待された型ではない場合にスローされる例外。 |
| LengthException | 長さが無効である場合にスローされる例外。 |
| OutOfRangeException | 不正なインデックスが要求された場合にスローされる例外。 |
| RuntimeException | 実行時にしか検出できないエラーが発生した場合にスローされる例外。 |
| OutOfBoundsException | 値が有効なキーではない場合にスローされる例外。 |
| OverflowException | 満杯のコンテナに要素を追加しようとした場合にスローされる例外。 |
| RangeException | プログラム実行中の範囲エラー(アンダーフロー/オーバーフロー以外の算術エラー)を示すためにスローされる例外。 |
| UnderflowException | 空のコンテナに対して要素の削除などの無効な操作を行った場合にスローされる例外。 |
| UnexpectedValueException | 値が想定される値のセットと一致しない場合にスローされる例外。 |
これらのSPL例外を適切に使い分けることで、「ロジック上のミス」なのか「実行環境由来の問題」なのかを明確に区別でき、より保守性の高いコードを書くことができます。
サンプル:OutOfBoundsExceptionをスローする
以下は、PHP配列に存在しないキーを参照した際にOutOfBoundsExceptionをスローする実用例です。
<?php
$arr=array("one"=>1, "two"=>2,"three"=>3,"four"=>4);
$key="ten";
try{
if (array_key_exists($key, $arr)==FALSE){
throw new OutOfBoundsException("key not found");}
else {
echo $arr[$key];}
}
catch (OutOfBoundsException $e){
echo $e->getMessage(). "\n";
}
?>
出力結果
key not found
array_key_exists()関数でキーの存在を確認し、見つからない場合にはOutOfBoundsExceptionを明示的に投げています。このように状況に応じて最適な例外クラスを選択することが、堅牢なPHPアプリケーション開発のポイントです。
-
Pryで例外をスマートに扱う方法|バックトレース表示からカスタマイズまで
Rails開発者なら、Railsコンソールを頻繁に使う方も多いのではないでしょうか。そして今や、RailsコンソールといえばPryが定番。素のIRBと比べると、その使い勝手は段違いです。 実はPryには、例外を扱う際に非常に便利な機能が標準で組み込まれています。この記事では、その中でも特に役立つ3つの機能を紹介します。 直近の例外の完全なバックトレースを表示する Pry(IRBでも同様)で例外が発生すると、通常は短縮されたバックトレースが表示されます。多くの場合それで十分ですが、詳細を確認したい場面もありますよね。 そんなときは wtf -v コマンドを使いましょう。直近の例外の完全な
-
Rubyでカスタム例外を作成する方法【初心者向けガイド】
Rubyでは、独自の例外クラスを簡単に作成できます。この記事では、カスタム例外を作るための基本的な手順を、コード例とともにわかりやすく解説します。 1. 新しいクラスを作成する Rubyにおいて、例外も他のオブジェクトと同じくクラスとして定義されています。新しい種類の例外を作りたい場合は、StandardError、あるいはそのサブクラスを継承したクラスを定義するだけでOKです。 class MyError < StandardError end raise MyError 慣例として、新しく作る例外クラスの名前は「Error」で終わるように命名します。また、カスタム例外をモジュ