PHP入門

【PHP入門】エラーと例外処理

2021年7月24日

はじめに

前回の記事では、PHPのコールバック関数について紹介しました。

本記事では、PHPのエラーと例外について紹介します。

PHPのエラー

エラーが発生したときの挙動

PHPでは実行中にエラーが発生しても、基本的には処理を続けようとします。ただし、続行できないFatal error(致命的なエラー)が発生した場合は処理を停止します。

例えば、次の例では「Warning(警告)」と「Fatal error(致命的なエラー)」を発生させています。

[エラーの例]

<?php

// 警告のエラーを発生させる(存在しないファイルを指定)
$fd = fopen("c:/temp/abc.txt","r");
echo "継続処理";

// 致命的なエラーを発生させる(存在しない関数を呼び出す)
a();
echo "継続処理";

?>

[実行結果]

Warning: fopen(c:/temp/abc.txt): Failed to open stream: No such file or directory in C:\xampp\htdocs\phpSample\lesson22\errorHandlerSample.php on line 4
継続処理
Fatal error: Uncaught Error: Call to undefined function a() in C:\xampp\htdocs\phpSample\lesson22\errorHandlerSample.php:9 Stack trace: #0 {main} thrown in C:\xampp\htdocs\phpSample\lesson22\errorHandlerSample.php on line 9

Warning(警告)の場合は、エラーメッセージを表示し処理を継続していますが、Fatal error(致命的なエラー)の場合は、継続処理を行わず処理を停止しています。

スポンサーリンク

このエラーの発生を感知して、何らかの処理を行うことをエラーハンドリングといいます。エラーハンドリングを行うには「set_error_handler()」関数を使用します。(ただし、Fatal errorはハンドリングしない)

set_error_handler関数の使い方

「set_error_handler()」関数を使用することで、エラーハンドリングを行うことができます。

[set_error_handler関数の使用例]

<?php

// エラー時の処理を登録
set_error_handler(function($errno, $errstr, $errfile, $errline){
    print "エラーが発生しました。$errno, $errstr <br />";
});

// 警告のエラーを発生させる(存在しないファイルを指定)
$fd = fopen("c:/temp/abc.txt","r");

?>

[実行結果]

エラーが発生しました。2, fopen(c:/temp/abc.txt): Failed to open stream: No such file or directory

PHPの例外

プログラム実行中に発生する予期せぬエラーのことを例外(Exception)といいます。

例外処理の流れ

例外が発生しそうな処理には、try文、catch文、finally文を使います。

PHPの例外

try{}内に例外が発生しそうな処理を記述します。

そして、catch{}内には例外が発生した時に行う処理を記述します。try{}内で例外が発生した場合、catch{}内の処理が動き出し、catchでは例外クラスのオブジェクトを受け取ります。例外クラスのオブジェクトには、どんな例外がどこで発生したのかの情報が格納されています。

最後に、finally{}内の処理は例外発生の有無に関わらず行う処理を記述します。finally文は省略可能なので、必要がなければ書かなくて大丈夫です。

正常時と例外発生時の処理の流れは次のとおりです。

正常時の流れ

  • try内の処理を実行
  • finally内の処理を実行(finallyは省略可能なのでfinallyが存在する場合のみ実行)

例外発生時の流れ

  • try内の処理を実行
  • 例外発生(例外が発生した時点でtry内の処理は中断しcatch文へ)
  • catch内の処理を実行
  • finally内の処理を実行(finallyは省略可能なのでfinallyが存在する場合のみ実行)

スポンサーリンク

try-catchの実装例

それでは、実際にソースコードで try-catch の使用例を紹介します。

PHPでは throw された例外(Exception)しか catch できません。(ただのエラーは catchできない)

どういう意味ですか?
例えば、次のようなケースではエラーをcatchできません。

[エラーをcatchできないケース]

<?php

try {
    // 警告のエラーを発生させる(存在しないファイルを指定)
    $fd = fopen("c:/temp/abc.txt","r");

} catch (Exception $e) {
    echo "例外が発生しました。".$e->getMessage();
}

?>

[実行結果]

Warning: fopen(c:/temp/abc.txt): Failed to open stream: No such file or directory in C:\xampp\htdocs\phpSample\lesson22\tryCatchSample.php on line 5
ほんとだ・・・。 エラーが発生しているのにcatchできていない・・・
エラーをcatchするには set_error_handler() 関数を使用します。

例外ではない ただのエラーをcatchするためには、「set_error_handler()」関数を使用します。エラーを「set_error_handler()」関数でハンドリングし、「set_error_handler()」関数内で例外を発生させます。

[try-catchの実装例]

<?php

// エラー時に例外をスローするように登録
set_error_handler(function($errno, $errstr, $errfile, $errline) {
    if (!(error_reporting() & $errno)) {
        return;
    }
    throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
});

try {
    // 警告のエラーを発生させる(存在しないファイルを指定)
    $fd = fopen("c:/temp/abc.txt","r");

} catch (Exception $e) {
    echo "例外が発生しました。".$e->getMessage();
}

?>

[実行結果]

例外が発生しました。fopen(c:/temp/abc.txt): Failed to open stream: No such file or directory

エラー発生時の流れ

  • try内の処理を実行
  • エラー発生(エラーが発生したのでset_error_handler()で登録した関数へ)
  • set_error_handler() で登録した関数の処理を実行(関数内で例外を発生させる。例外が発生したのでcatch文へ)
  • catch内の処理を実行
  • finally内の処理を実行(finallyは省略可能なのでfinallyが存在する場合のみ実行)
なるほど、set_error_handler()関数内で例外を発生させることで、catchできるようにしているのですね。・・・ややこしい

helpful