PHP Try Catch の例: 例外とエラー処理のチュートリアル

⚡ スマートサマリー

PHPにおけるエラー処理と例外処理は、生のエラーをそのまま公開するのではなく、予期せぬ状況を適切に管理することで、アプリケーションの安定性とセキュリティを維持します。このチュートリアルでは、エラーと例外の違い、die文、カスタムエラーハンドラ、エラー報告レベル、そして複数の例外タイプに対応したtry、throw、catch例外モデルについて説明します。

  • ⚠️ エラーと例外: エラーは一般的に回復不可能な事象であるのに対し、例外はプログラムが捕捉して処理できる予期せぬ結果である。
  • 🛡️ 取り扱い理由: エラーを適切に処理することで、見苦しい出力を防ぎ、ユーザーを保護し、攻撃者が悪用できるような情報の漏洩を回避できます。
  • 🛑 ダイステートメント: die関数はメッセージを表示してスクリプトを停止します。これは、何らかのエラーが発生した場合に実行を素早く停止させる方法です。
  • 🛠️ カスタムハンドラー: set_error_handler() はエラーを独自の関数にルーティングするため、ログ記録、メール送信、メッセージのフォーマットなどを自由に行うことができます。
  • 📢 エラー報告: error_reporting() や E_ALL などのレベルは、PHP が表示する警告や通知を制御します。これは開発中に役立ちます。
  • 🧲 試す、投げる、キャッチする: tryブロックはリスクのあるコードを実行し、throwは例外を発生させ、catchは例外オブジェクトのメソッドを使用して例外を処理します。
  • 🤖 AIアシスト: AIツールは既存のコードにtry-catch処理を追加し、複雑なスタックを説明することができます。 trace またはエラーメッセージ。

PHPのエラー処理と例外処理

例外とは何ですか?

エラーとは、プログラム自体では処理できない、予期しないプログラムの結果です。

エラーはプログラムを修正することで解決されます。 エラーの例としては、実行が決して停止しない無限ループが挙げられます。

例外とは、プログラム自体が処理できる予期せぬプログラム結果のことである。

例外の例としては、存在しないファイルを開こうとした場合などが挙げられる。

この例外は、ファイルを作成するか、ユーザーにファイルの検索オプションを提示することで処理できます。

例外処理を行う理由とは?

  • エンドユーザーにとって非常に迷惑または不快な結果となる可能性のある、予期せぬ結果が当社のページで発生しないようにします。
  • 悪意のあるユーザーがアプリケーションを攻撃するために使用する可能性のある情報を公開しないことで、アプリケーションのセキュリティを向上させます。
  • PHPの例外処理は、予測可能なエラーが発生した場合に、プログラムの通常の流れを変更するために使用されます。

PHPエラー処理

エラーが発生した場合、構成設定に応じて、 PHP 発生したエラーに関連する情報を含むエラー メッセージを Web ブラウザに表示します。

PHPにはエラーを処理するための様々な方法が用意されています。ここでは、よく使われる3つの方法を見ていきましょう。

  1. ダイステートメント die関数は、echo関数とexit関数を一つにまとめたものです。エラーが発生した際にメッセージを出力し、スクリプトの実行を停止したい場合に非常に便利です。
  2. カスタムエラーハンドラ – これらは、エラーが発生するたびに呼び出されるユーザー定義関数です。
  3. PHPエラーレポート エラーメッセージは、PHPのエラー報告設定によって異なります。この方法は、エラーの原因が全く分からない開発環境で非常に役立ちます。表示される情報は、アプリケーションのデバッグに役立ちます。

エラー処理の例

それでは、エラー処理ルーチンを用いた簡単な例をいくつか見ていきましょう。

計算式で数値をゼロで割ってしまう可能性があると仮定しましょう。PHPが生のエラーを表示するのではなく、そのようなケースを適切に処理したいと考えます。

以下のコードは上記の例を実装しています。

<?php
$denominator = 0;
echo 2 / $denominator;
?>

simple_error.php ファイルを phptuts フォルダに保存したと仮定して、 URL http://localhost/phptuts/simple_error.php

以下の結果が得られます。

PHPエラー処理

上記の結果からわかるように、アプリケーションがプロフェッショナルに見えず、ユーザーにとって煩わしいものになる可能性があります。

上記のコードを修正し、アプリケーションのエラーハンドラを作成します。

<?php
$denominator = 0;
if ($denominator != 0) {
echo 2 / $denominator;
} else {
echo "cannot divide by zero (0)";
}
?>

上記のコードを error_handling.php として保存したと仮定して、 URL http://localhost/phptuts/error_handling.php

PHP の PHP 例外ハンドル

注意: 「ファイルが見つかりません」のような生のメッセージを表示する代わりに、上記のようなメッセージを表示することは、セキュリティ上の良い対策です。

カスタムエラーハンドラーを使用する別の例を見てみましょう。

カスタム エラー ハンドラーはデフォルトの PHP エラー処理関数として設定され、基本的にエラー番号とメッセージを表示します。

以下のコードは、上記の例の実装を示しています。

<?php
function my_error_handler($error_no, $error_msg)
{
echo "Oops, something went wrong:";
echo "Error number: [$error_no]";
echo "Error Description: [$error_msg]";
}
set_error_handler("my_error_handler");
echo (5 / 0);
?>

Video Cloud Studioで URL http://localhost/phptuts/custom_error_handler.php以下のような結果が得られます。

PHPエラー処理

上記の例からもわかるように、カスタムエラーハンドラーは次のような点で強力です。

  • これらを使用すると、エラー メッセージをカスタマイズできます。
  • カスタムエラーハンドラーには、ファイルやデータベースへのエラーログ記録、開発者へのメール送信、その他同様の処理を含めることもできます。

それでは、3つ目のエラー処理方法を見ていきましょう。ここでは、PHPに組み込まれているerror_reporting関数を使用します。基本的な構文は以下のとおりです。

<?php
error_reporting($reporting_level);
?>

ここに、

  • 「error_reporting」はPHPのエラー報告関数です。
  • 「$reporting_level」はオプションであり、レポートレベルを設定するために使用できます。レポートレベルが指定されていない場合、PHPはphp.iniファイルで指定されているデフォルトのエラーレポートレベルを使用します。
報告レベル 詳細説明 例:
E_警告 警告メッセージのみを表示します。 スクリプトの実行を停止しません エラー報告(E_WARNING);
E_NOTICE プログラムの通常の実行中に発生する可能性のある通知、またはエラーの可能性がある通知を表示します。 error_reporting(E_NOTICE);
E_USER_ERROR ユーザーが生成したエラー、つまりカスタムエラーハンドラーを表示します。 error_reporting(E_USER_ERROR);
E_USER_WARNING ユーザーが生成した警告メッセージを表示します エラー報告(E_USER_WARNING);
E_USER_NOTICE ユーザーが作成した通知を表示します エラー報告(E_USER_NOTICE);
E_RECOVERABLE_ERROR 致命的ではないエラーを表示し、カスタムエラーハンドラを使用して処理できます。 エラー報告(E_RECOVERABLE_ERROR);
E_ALL すべてのエラーと警告を表示します エラー報告(E_ALL);

エラーと例外の違い

  • 例外はスローされ、捕捉されることを前提としているが、エラーは一般的に回復不可能である。
  • 例外処理はオブジェクト指向的に行われます。つまり、例外が発生すると、例外の詳細を含む例外オブジェクトが作成されます。

下の表は、例外オブジェクトのメソッドを示しています。

方法 詳細説明 例:
getMessage() 例外のメッセージを表示します
<?php
echo $e->getMessage();
?>
取得するCode() 例外を表す数値コードを表示します。
<?php
echo $e->getCode();
?>
getFile() 例外が発生したファイル名とパスを表示します
<?php
echo $e->getFile();
?>
getLine() 例外が発生した行番号を表示します
<?php
echo $e->getLine();
?>
取得するTrace() 背面の配列を表示しますtrac例外の前の e
<?php
print_r( $e->getTrace());
?>
getPrevious() 現在の例外の前に前の例外を表示します
<?php
echo $e->getPrevious();
?>
取得するTraceAsString() 背面を表示しますtrac例外を配列ではなく文字列として扱う
<?php
echo $e->getTraceAsString();
?>
__toString() 例外全体を文字列として表示します
<?php
echo $e->__toString();
?>

以下は例外をスローするための基本的な構文です。

<?php
throw new Exception("This is an exception example");
?>

ここに、

  • 「throw」は例外をスローするために使用されるキーワードです
  • 「new Exception(…)」は例外オブジェクトを作成し、「これは例外の例です」という文字列をメッセージパラメータとして渡します。

上記のコードは次のメッセージを出力します。

PHP の PHP 例外ハンドル

次に、例外処理(throwとcatch)を実装した例を見ていきましょう。上記の例を修正し、try、throw、catchを追加します。

基本的な構文は次のとおりです。

<?php
try {
// code goes here that could potentially throw an exception
}
catch (Exception $e) {
// exception handling code goes here
}
?>

ここに、

  • 「try{…}」は、例外が発生する可能性がある実行されるコードのブロックです。
  • 「catch(Exception $e){…}」は、スローされた例外をキャッチし、例外オブジェクトを変数 $e に割り当てるコード ブロックです。

以下のコードは、try、throw、catch を実装した基本的な例外処理の例を示しています。このプログラムは意図的に例外をスローし、それをキャッチします。

<?php
try {
$var_msg = "This is an exception example";
throw new Exception($var_msg);
}
catch (Exception $e) {
echo "Message: " . $e->getMessage();
echo "";
echo "getCode(): " . $e->getCode();
echo "";
echo "__toString(): " . $e->__toString();
}
?>

Video Cloud Studioで URL http://localhost/phptuts/exception_handling.php以下のような結果が得られます。

PHP の PHP 例外ハンドル

また、発生した例外の種類に応じて、1つのPHP try文に対して複数の例外を作成することも可能です。

に関する記事を参照してください MySQLPHP による複数例外の実装例のためのデータアクセス。

複数の例外

複数の例外は、複数の catch ブロックを使用してスローされた例外を処理します。複数の例外は、次のような場合に役立ちます。

  • スローされた例外に応じてカスタマイズされたメッセージを表示したい
  • スローされた例外に応じて固有の操作を実行したい

以下のフローチャートは、複数の例外処理がどのように機能するかを示しています。

複数の例外

複数の例外処理を用いる例を見てみましょう。渡された分母で数値を割るコードを修正します。

想定される例外は2種類あります。

  • ゼロ除算
  • 負の数による除算

簡潔にするため、catch ブロックでは例外の種類のみを表示します。例外をスローするには、PHP の組み込みクラスである Exception クラスを使用します。ここでは、Exception クラスを継承する 2 つのクラスを作成し、それらを使用して例外をスローします。

以下のコードは実装を示しています。

<?php
class DivideByZeroException extends Exception {};
class DivideByNegativeException extends Exception {};
function process($denominator)
{
try
{
if ($denominator == 0)
{
throw new DivideByZeroException();
}
else if ($denominator < 0)
{
throw new DivideByNegativeException();
}
else
{
echo 25 / $denominator;
}
}
catch (DivideByZeroException $ex)
{
echo "DIVIDE BY ZERO EXCEPTION!";
}
catch (DivideByNegativeException $ex)
{
echo "DIVIDE BY NEGATIVE NUMBER EXCEPTION!";
}
catch (Exception $x)
{
echo "UNKNOWN EXCEPTION!";
}
}
process(0);
?>

コードのテスト

multiple_exceptions.php は phptuts フォルダに保存済みであると仮定します。

を参照 URL http://localhost/phptuts/multiple_exceptions.php

PHP の PHP 例外ハンドル

PHP ファイルに戻り、次の図に示すように、パラメータとして -1 を渡します。

PHP の PHP 例外ハンドル

を参照 URL http://localhost/phptuts/multiple_exceptions.phpどのような結果が得られますか?次に、パラメータとして3を渡してください。どのような結果が得られますか?

最後にブロックとPHP 7エラーモデル

最新のPHPでは、上記のモデルに2つの重要な要素が追加されています。finallyブロックは、例外がスローされたかどうかに関わらず、tryとcatchの後に実行されるため、ファイルやデータベース接続を閉じるなどのクリーンアップ処理に最適です。

PHP 7以降、以前は致命的エラーとされていた多くのエラーがErrorオブジェクトとしてスローされるようになりました。ExceptionとErrorはどちらもThrowableインターフェースを実装しているため、catch(\Throwable $e)ブロックでどちらのエラーも処理できます。

<?php
try {
$result = 10 / 0;
} catch (DivisionByZeroError $e) {
echo "Caught: " . $e->getMessage();
} finally {
echo "This message always runs";
}
?>

ここでは、PHP 8 ではゼロ除算を行うと DivisionByZeroError が発生し、catch ブロックがそれを報告し、finally ブロックは常に実行され、エラーが発生したかどうかに関わらずそのメッセージが出力されます。

よくあるご質問

本番環境では、php.ini ファイルで display_errors を Off に、log_errors を On に設定し、error_log にファイルを指定します。また、error_log('message') を呼び出すことで、訪問者に何も公開することなくカスタムエントリを記録できます。

try-catch は、throw キーワードでスローされた例外を処理します。set_error_handler は、従来の PHP エラーと警告をインターセプトします。PHP 7 以降では、以前のエラーの多くが Error オブジェクトとしてスローされるため、これらもキャッチできます。

捕捉されない例外は致命的なエラーとなり、スクリプトを停止し、スタックトレースを含む「捕捉されない例外」メッセージを出力します。 trace. set_exception_handler で設定されたグローバルハンドラは、最終手段としてこれらを捕捉できます。

はい。AIは、リスクの高い操作をtry-catchブロックで囲み、適切な例外タイプを選択し、クリーンアップのためのfinallyブロックを追加し、エラーをログに記録することができます。 Rev必要な例外を見逃さないように注意してください。

はい。メッセージを貼り付けて trac例えば、AIは障害が発生している行、そこに至るまでの呼び出しチェーン、そして考えられる原因を特定し、nullチェックや引数の修正などの修正案を提案することができます。