PHPエラーハンドリング完全ガイド!5つの手順で例外を理解・活用

PHPエラーハンドリングを詳細に説明するためのグラフィックPHP
この記事は約12分で読めます。

 

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

基本的な知識があればカスタムコードを使って機能追加、目的を達成できるように作ってあります。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を凌駕する現役のプログラマチームによって監修されています。

サイト内のコードを共有する場合は、参照元として引用して下さいますと幸いです

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

PHPを用いたプログラミングにおいて、一歩進んだスキルとして必須なのが「例外処理」です。

この記事を読めば、PHPの例外処理が完全に理解でき、その活用方法を身につけることができるでしょう。

ここでは例外処理の基本から詳細な使い方、注意点、そしてカスタマイズ方法まで一通りを解説します。

さらに、実際のコードを用いて具体的な方法を見ていきましょう。

●PHPの例外とは

PHPの例外(Exception)は、プログラム実行中に何か問題が発生したときにスローされます。

例外が発生した時点で通常のプログラムの実行は停止し、例外を処理するためのコードが実行されます。

例外の役割は大きく2つあります。

1つ目は、エラーが発生した時にその情報を捉え、適切に処理することでプログラムの安定性を保つこと。

2つ目は、エラー情報を利用者や開発者に明示的に伝えることで、エラーの原因解析を容易にすることです。

●例外処理の基本

例外処理の基本は、”try-catch”ブロックを使用することです。

このブロックは、例外が発生する可能性のあるコードを「try」ブロック内に記述し、その後に来る「catch」ブロックで例外をキャッチし、それに対する適切な処理を記述します。

○例外の生成とスロー

例外の生成は、newを使用してExceptionクラスまたはその派生クラスのインスタンスを作成します。

そして、”throw”キーワードを使って例外をスローします。

このスローされた例外は、”catch”ブロックでキャッチされます。

○例外のキャッチと処理

例外をキャッチするには、”catch”ブロックを使用します。

このブロックでは、引数としてスローされた例外を取得し、その情報を利用して例外に対する適切な処理を行います。

例外が発生した場合、プログラムは直ちにその処理を停止し、最も近い”catch”ブロックを探します。

この時、該当の”catch”ブロックがない場合や、例外が未処理の場合はプログラムは終了します。

このため、プログラムの安定性を保つためには、可能な限り全ての例外を適切にキャッチし、処理することが重要です。

●例外処理の詳細な使い方

ここでは、例外処理のさらに詳細な使い方について解説します。

下記のサンプルコードを見ていきましょう。

○サンプルコード1:基本的な例外の使用方法

<?php
try {
    echo "このコードブロックはエラーを発生させます。";
    throw new Exception("これはエラーメッセージです");
} catch (Exception $e) {
    echo "エラーがキャッチされました: ",  $e->getMessage(), "\n";
}
?>

このコードでは、まずtryブロック内でエラーを発生させています。

そして、それをcatchブロックでキャッチし、エラーメッセージを出力しています。

これは例外処理の基本形であり、これだけでも多くのエラーハンドリングに対応できます。

○サンプルコード2:カスタム例外の使用方法

<?php
class MyException extends Exception {}

try {
    throw new MyException('これはカスタム例外です');
} catch (MyException $e) {
    echo 'MyExceptionをキャッチしました: ',  $e->getMessage(), "\n";
} catch (Exception $e) {
    echo '未知の例外をキャッチしました: ',  $e->getMessage(), "\n";
}
?>

このコードでは、まずExceptionクラスを継承したカスタム例外クラスを定義しています。

そして、そのカスタム例外をスローし、キャッチしています。

この方法を使えば、独自の例外クラスを定義し、その特性を活用したエラーハンドリングが可能になります。

○サンプルコード3:例外処理のネスト

<?php
try {
    echo "外側のtryブロック\n";
    try {
        echo "内側のtryブロック\n";
        throw new Exception("内側の例外");
    } catch (Exception $e) {
        echo "内側のcatchブロック\n";
    }
    throw new Exception("外側の例外");
} catch (Exception $e) {
    echo "外側のcatchブロック: ", $e->getMessage(), "\n";
}
?>

このコードでは、try-catchブロックがネストしています。

つまり、tryブロック内に別のtry-catchブロックが存在しています。

この方法を使えば、各段階で発生した例外をそれぞれ異なる方法で処理することが可能です。

○サンプルコード4:例外処理とエラーハンドリングの組み合わせ

<?php
set_error_handler(function ($severity, $message, $file, $line) {
    throw new ErrorException($message, $severity,

 $severity, $file, $line);
});

try {
    echo "エラーハンドリングと例外処理の組み合わせ\n";
    trigger_error("ユーザエラー");
} catch (Exception $e) {
    echo "エラーがキャッチされました: ",  $e->getMessage(), "\n";
}
?>

このコードでは、set_error_handler関数を用いて自分自身のエラーハンドラを設定しています。

そして、エラーが発生した場合にはErrorExceptionをスローします。

この方法を使えば、エラーハンドリングと例外処理を組み合わせることが可能です。

●例外処理の応用例

ここでは、さらに応用的な例外処理の方法について解説します。

下記のサンプルコードを見ていきましょう。

○サンプルコード5:複数の例外タイプを捕捉する

<?php
class MyException extends Exception {}
class AnotherException extends Exception {}

try {
    throw new MyException('これはMyExceptionです');
} catch (MyException | AnotherException $e) {
    echo 'MyExceptionまたはAnotherExceptionをキャッチしました: ',  $e->getMessage(), "\n";
} catch (Exception $e) {
    echo '未知の例外をキャッチしました: ',  $e->getMessage(), "\n";
}
?>

このコードでは、MyExceptionとAnotherExceptionの二つの異なる例外クラスを定義しています。

そして、それらのどちらかをスローした場合、それらを一つのcatchブロックでキャッチしています。

これにより、複数の異なる例外タイプを一つのcatchブロックで捕捉することができます。

○サンプルコード6:例外チェーン

<?php
try {
    try {
        throw new Exception('内側の例外');
    } catch (Exception $e) {
        throw new Exception('外側の例外', 0, $e);
    }
} catch (Exception $e) {
    do {
        printf("%s:%s\n", get_class($e), $e->getMessage());
    } while($e = $e->getPrevious());
}
?>

このコードでは、内側のtryブロックで発生した例外を捕捉し、その情報を持った新たな例外をスローしています。

これにより、例外が連鎖的に発生した場合でも、それらの情報をすべて捕捉することができます。

これを例外チェーンと言います。

○サンプルコード7:フィナリー節の使用

<?php
try {
    echo "tryブロック\n";
    throw new Exception('これは例外です');
} catch (Exception $e) {
    echo "catchブロック\n";
} finally {
    echo "finallyブロック\n";
}
?>

このコードでは、tryブロックとcatchブロックの後にfinallyブロックを使用しています。

finallyブロック内のコードは、例外の発生有無に関わらず必ず実行されます。

これにより、例外の発生に関わらず共通の処理を行うことができます。

●例外処理の注意点と対処法

例外処理の実装には注意が必要です。

下記の項目では、意図しない例外を防止する方法と、例外処理のベストプラクティスについて解説します。

○意図しない例外の防止

PHPでは、意図しない例外がスローされることがあります。

これを防ぐためには、適切なエラーハンドリングが必要です。

<?php
function divide($numerator, $denominator){
    if($denominator == 0){
        throw new Exception("0で割ることはできません");
    }
    return $numerator / $denominator;
}

try {
    echo divide(10, 0);
} catch (Exception $e) {
    echo 'エラー: ',  $e->getMessage(), "\n";
}
?>

このコードでは、分母が0の場合に例外をスローする関数divideを定義しています。

この関数をtryブロック内で呼び出し、例外が発生した場合にそれをキャッチしています。

このように、エラーが発生し得る箇所を予測し、適切に例外をスローすることで、意図しない例外の発生を防ぐことができます。

○例外処理のベストプラクティス

例外処理におけるベストプラクティスを紹介します。

  • 例外は、例外的な状況でのみスローすべきです。
    通常の制御フローで例外を使用すると、コードの可読性を損なう可能性があります。
  • 例外メッセージは、何が問題でどのように解決すればよいかを明確に伝えるべきです。
    これにより、エラーの原因を追跡しやすくなります。
  • 例外は可能な限り具体的なものをスローするべきです。
    つまり、一般的なExceptionクラスではなく、問題を具体的に示す独自の例外クラスを作成することを検討してみてください。

以上の注意点とベストプラクティスを頭に入れつつ、例外処理の実装を進めていくと、より効果的なエラーハンドリングが可能になります。

●例外処理のカスタマイズ方法

例外処理はPHPの強力なツールであり、その機能はカスタマイズが可能です。

独自の例外クラスを作成することで、具体的なエラー状況を反映した例外処理を実現することができます。

○カスタム例外クラスの作成

例外クラスをカスタマイズすることで、エラーの種類に応じた独自の例外処理を実装することが可能です。

ここでは、独自の例外クラスを作成する方法を示します。

<?php
class ZeroDivisionException extends Exception {
    public function __construct($message = "0で割ることはできません", $code = 0, Throwable $previous = null) {
        parent::__construct($message, $code, $previous);
    }
}

function divide($numerator, $denominator){
    if($denominator == 0){
        throw new ZeroDivisionException();
    }
    return $numerator / $denominator;
}

try {
    echo divide(10, 0);
} catch (ZeroDivisionException $e) {
    echo 'エラー: ',  $e->getMessage(), "\n";
}
?>

このコードでは、ZeroDivisionExceptionという新しい例外クラスを作成しています。

この例では、0で割る操作を行う場合にこの例外をスローしています。

それぞれの例外が明確に示されることで、エラーハンドリングが容易になり、より具体的なエラー情報を得ることができます。

以上のカスタマイズにより、PHPの例外処理は、アプリケーションの要件に応じて柔軟に対応することが可能です。

ここまで、例外処理の基本から具体的な利用例、ベストプラクティス、カスタマイズ方法までを解説してきました。

これらの知識を活用して、より効果的なエラーハンドリングを行うことができます。

まとめ

この記事では、PHPの例外処理の理解と使い方、そしてそのカスタマイズ方法を詳細に学んできました。

例外処理はプログラムの安全性と信頼性を向上させるための重要な概念であり、理解して活用することが重要です。

まず、例外処理の基本的な概念を説明し、例外処理がプログラムの中でどのように動作するのかを理解しました。

そして、特定のエラーが発生したときにそれを捕捉して適切に処理するためのtry-catch構文の使い方を学びました。

次に、例外処理のベストプラクティスを探究しました。

これには、例外の適切な使用、例外処理の適切な場所、例外のチェインと再スローなどが含まれます。

そして、カスタム例外クラスの作成方法を学びました。

これにより、エラーの種類に応じた独自の例外処理を実装することが可能になります。

独自の例外クラスを作成することで、より具体的なエラー情報を提供し、エラーの解決を容易にすることができます。

以上の全てを組み合わせることで、より安全で信頼性の高いアプリケーションを開発することが可能になります。

例外処理は一見複雑に見えるかもしれませんが、基本概念を理解し、適切に使用することで、プログラムの品質を大幅に向上させることができます。

そのため、この記事で学んだ内容をしっかりと理解し、自身のコードに反映させることを強く推奨します。