PHP Manual

PHPにおける例外とその捕捉

16. 02. 2020

Obsah článku

例外はオブジェクト指向プログラミングのツールで、アプリケーションのエラーを投げたり、処理したりする(treat)ためのエレガントな方法を提供します。

例外はまず投げられ (thrown)、処理され (try)、捕捉されます (catch) 。投擲のみ必須です。

例外発生哲学

例外が登場する以前のプログラミングにおけるエラー処理は、関数の戻り値を頼りに、自分なりにキャッチしてそれなりに振る舞うしかなく、非常に複雑なものでした。

実際、関数そのものはエラー処理を強制しないので、致命的な問題になりかねませんが、これについては David が Programmers don't ignore errors で書いてくれてますね。

エラー処理を忘れている例。

// ディスクからディスクへの移動
copy('c:/oldfile', 'd:/newfile');
unlink('c:/oldfile');
// 最初の操作に失敗した場合、ファイルは回復不能に削除される

これは、copy()関数からの出力を処理する正しい方法は、続行せずにエラーを投げることだからです。古き良き時代の関数の場合、次のような感じでしょうか。

function backup(): bool
{
if (copy('c:/oldfile', 'd:/newfile')) {
return unlink('c:/oldfile');
}
return false;
}

この backup() 関数は、 copy() 関数が失敗せず、かつ unlink() 関数が true を返した場合にのみ、 true を返します。そうでなければ、false を返す。

しかし、これでアプリケーションは大丈夫なのでしょうか?そんなことはありません!なぜなら、今は backup() 関数を呼び出した時点でその出力を処理しなければならず、もし失敗したらその理由すらわからなくなってしまうからです。要するに、falseを返すので、何らかの方法で自分自身でエラーを検出しなければならないのです。この場合、プログラマーがエラー処理をあきらめたり、単に何かを処理し忘れたりして、そのためにアプリケーションが検出しにくいエラーを投げることがよくあるということがわかったのはよかったと思います。

この問題を解決するには、例外処理で強制的に処理し、処理しない場合はアプリケーションが完全にクラッシュし、必ず原因がわかるようにすることです。

基本的な例外の定義

PHP では、例外はこれから使うネイティブな Exception クラスで実装される特別な種類のインターフェイスです。

プログラムの一部の処理に失敗した場合は、問題を説明する例外を投げるだけです。

if (copy('c:/oldfile', 'd:/newfile') === false) {
throw new \Exception('ファイル "oldfile "をコピーできません。');
}

例外を投げるには、 throw キーワードを使用し、その後に例外の発生したクラスのインスタンスを作成します。また、他の方法(例えば変数から渡すなど)でもインスタンスを取得することができ、例外インスタンスを生成しただけでは、そのインスタンスは投げられません。

Exceptionクラスのコンストラクタの最初の引数は、例外のテキストを受け取ります。また、実行される操作の情報とデータへの参照を含めるとよいでしょう。例えば、ファイルのコピーに失敗した場合、ファイル名を渡すのが良い方法である。SQLクエリの実行に失敗した場合は、再度、実行中のクエリを渡します。これは、後でエラーを処理するときに、何が問題なのかを正確に把握することができるので、非常に役に立ちます。

例外処理

例えば、データをバックアップする関数 backup() があって、2つのエラーを投げることがあるとします。

function backup(): void
{
if (copy('c:/oldfile', 'd:/newfile')) {
if (unlink('c:/oldfile') === false) {
throw new \Exception('古いファイルを削除することができません。');
}
}
throw new \Exception('バックアップファイルのコピーができない。');
}

この関数は出力を返さないことに注意してください。また、定義では void 型を指定しています。成功はエラーが投げられない状態とみなされ、正のシナリオを扱う必要がないため、この関数は何も返す必要がありません。

仮に、処理を行わないアプリケーションでこの機能を使う場合、例えば次のようになる。

echo 'ファイルをバックアップする...';
backup();
echo 'バックアップが完了しました。';

それが通常の動作になります。ただし、エラーが発生した場合は、スクリプトは自動的に終了し、出力に例外テキストが表示されます。重要なのは、コードの実行を継続しないことで、データの破損が起こらないことが分かっていることです。

もし実行を続けたいのであれば、trycatch コンストラクトを使って、エラーを ** 一掃する必要があります。

echo 'ファイルをバックアップする...';
try {
backup();
} catch (\Exception $e) {
echo 'バックアップに失敗しました。' . $e->getMessage();
}
echo 'バックアップが完了しました。';

例外が発生すると、catch()領域のコード(データ型が一致すれば例外を受け入れる)が呼び出され、内部のコードが実行されます。

例外クラスのインスタンスを常に取得します。このインスタンスは、例えば、エラーメッセージを表示するために使用することができ、これは getMessage() メソッドによって処理されます。また、エラーを含むファイルのディスクパスを返す getFile() メソッド、エラーステータスコードを返す getCode() メソッド、例外が発生した行番号を返す getLine() メソッドも知っていると便利です。

用意された例外

基本的な例外である Exception 以外にも、PHP にはさまざまなユースケースに適した定義済みの例外型があります。

データ型|説明|||。
論理例外(LogicException) : 論理的なエラー。
BadFunctionCallException
BadMethodCallException
InvalidArgumentException
OutOfRangeException
LengthException
DomainException
RuntimeException
OverflowException
UnderflowException
OutOfBoundsException
RangeException
UnexpectedValueException

LogicExceptionRuntimeException` の例外は、適切なプログラム設計によって防止する必要があります。個人的には、ファイルへの書き込み失敗や外部サービスとの通信など、例外的な状況にのみ使用しています。

私は RuntimeException を全くキャッチせず、アプリケーションを失敗させることをお勧めします。これは通常、重大な問題であり、できるだけ早く報告されるべきものです。

Jan Barášek   Více o autorovi

Autor článku pracuje jako seniorní vývojář a software architekt v Praze. Navrhuje a spravuje velké webové aplikace, které znáte a používáte. Od roku 2009 nabral bohaté zkušenosti, které tímto webem předává dál.

Rád vám pomůžu:

Související články

1.
11.
Status:
All systems normal.
2024