[PHP] エラー出力の制御について

PHPのエラー出力の制御は、php.iniのerror_reportingに設定する方法と、もしくはプログラム実行時に関数で設定する方法があります。

プログラムで設定する場合は、ini_set関数で設定するか、専用のerror_reporting関数で設定する方法があります。

error_reporting関数

error_reporting関数は、引数にエラーの種類を表す定数を指定し、どの種類のエラーを出力するのかを設定することが出来ます。

なお引数の設定値はint型のため数値リテラルを設定することもできますが、組み込み定数を使って指定することが推奨されています。

公式マニュアル: https://www.php.net/manual/ja/function.error-reporting.php

error_reporting関数のシグネチャ

1. error_reporting関数
引数 int (error_level)

※PHP8.0からnullの指定が可能、nullの場合はデフォルト(32767)が設定され、すべてのエラーを出力する設定になる。

戻り値 int

$error_level引数指定ありの場合は、変更前のエラーレベルを返す。
$error_level引数指定なしの場合は、現在のエラーレベルを返す。

error_levelについて

error_levelはPHPコアに組み込まれており、いつでも利用できます。

2. error_level定数
E_ERROR (1) 重大なエラー、復帰不可能なためスクリプトは中断する
E_WARNING (2) 実行時の警告、スクリプトは続行できる
E_PARSE (4) コンパイル時のパースエラー
E_NOTICE (8) 実行時の警告、スクリプトは続行できる
E_ALL (32767) 全てのエラーを出力する
0 全てのエラーを出力しない、定数は無し
~0 0の反転、すべてのエラーを出力する
これは将来的に新たなエラーレベルが追加された場合でもカバーできるように用意されている指定方法で、-1を指定しても同じ効果がある

複数エラーレベルの指定方法

各定数はビット演算子を使って複数指定できます。

例)E_ERRORとE_WARNINGを出力する

error_reporting(E_ERROR | E_WARNING);

例)E_NOTICE以外の全てのエラーを出力する

error_reporting(E_ALL & ~E_NOTICE);

E_ERROR

E_ERRORを設定すると、続行不可能なエラーが発生した場合、Fatal errorが出力されます。

コード

以下の例では、0による除算を行いFatal errorが発生します。

error_reporting(E_ERROR);

echo "error_reporting = ", error_reporting(), "\n";

$var = 10 / 0;

echo "var = ", $var, "\n";

実行結果

$ php test_error.php
error_reporting = 1

Fatal error: Uncaught DivisionByZeroError: Division by zero in .\test_error.php:6
Stack trace:
#0 {main}
  thrown in .\test_error.php on line 6

E_WARNING

E_WARNINGを設定すると、警告発生時にWarningを出力します。

コード

以下の例では、未定義の変数$xと$yを使って処理をしていますが、この場合は警告(Warning)が発生します。

error_reporting(E_WARNING);

echo "error_reporting = ", error_reporting(), "\n";

$var = $x + $y;

echo "var = ", $var, "\n";

実行結果

実行結果を確認すると、警告(Warning)は発生しますが、処理は続行し最終的に「var = 0」を出力しているのが分かります。

$ php test_error.php
error_reporting = 2

Warning: Undefined variable $x in .\test_error.php on line 6

Warning: Undefined variable $y in .\test_error.php on line 6
var = 0

E_PARSE

E_PARSEに関しては構文エラーを指し、このエラーに関してはスクリプトを読み込んだ時点でチェックされ、エラーを検知するとスクリプトは何も実行されません。したがってerror_reporting関数による抑止はできません。

コード

以下の例では最後のechoの文で構文エラーになっていて、実行するとParse errorが発生します。

//error_reporting(E_PARSE);

echo "error_reporting = ", error_reporting(), "\n";

$var = "E_PARSE";
echo "TEST" $var, "\n";

実行結果

$ php test_error.php

Parse error: syntax error, unexpected variable "$var",
    expecting "," or ";" in .\test_error.php on line 7

E_NOTICE

PHP 8系からエラーレベルが見直され全体的に厳しくなりました。7系以前でE_NOTICEだったものはE_WARNINGへ、E_WARNINGだったものはE_ERRORへと変更されています。

set_error_handler関数

set_error_handler関数を使うと、実行時に発生するエラーをユーザー定義関数(callable型)で制御することが出来ます。

set_error_handler関数の引数について

3. set_error_handler関数の引数
第一引数 callable $callback

callable型のcallback関数を指定し、この中にエラー発生時の制御を記述する

第二引数 int $error_levels

ハンドリング対象とするエラーレベルを定数で指定する。この引数は任意で、省略した場合E_ALLとなり、すべてのエラーがハンドリング対象となる。

set_error_handler関数に指定するcallback関数について

callback関数は引数を4つ指定して定義します。この関数が呼ばれる際、引数にエラー情報が入ってきますのでそれらを使用し、独自の制御を入れてエラーを制御することが出来ます。

4. set_error_handler関数に指定するcallback関数の引数
第一引数 int $errno

エラーレベル

第二引数 string $errstr

エラーメッセージ

第三引数 string $errfile

エラーが発生したPHPファイルのファイルパス

第四引数 int $errline

エラーが発生した行番号

[実装例]エラー発生時に独自の例外をスローする

コード

以下の例ではすべてのエラーをハンドリングし、独自の例外をスローする例です。コールバック関数内では引数で渡ってくるエラー情報を出力しています。

class TestException extends Exception {}

set_error_handler(
    function ($errno, $errstr, $errfile, $errline) {
        echo "errno = ", $errno, "\n";
        echo "errstr = ", $errstr, "\n";
        echo "errfile = ", $errfile, "\n";
        echo "errline = ", $errline, "\n";
        echo "--------------------\n";
        throw new TestException("[TEST]" . $errstr, 123);
    }
);

try {
    $i++;
} catch(Exception $e) {
    echo "Error No = ", $e->getCode(), "\n";
    echo "Exception = ", get_class($e), "\n";
    echo $e->getMessage() , "\n";
}

実行結果

実行結果を確認すると、まずエラーがコールバック関数によりハンドリングされて、スローしたTestExceptionはエラーが発生したtry-catch内で補足されていることが分かります。

$ php test_error.php
errno = 2
errstr = Undefined variable $i
errfile = .\test_error.php
errline = 16
--------------------
Error No = 123
Exception = TestException
[TEST]Undefined variable $i

ThrowableインターフェースとErrorクラスについて

Throwableインターフェース

PHP7で導入された全てのスロー可能なオブジェクトの基底インターフェースです。ExceptionクラスやErrorクラスもこれを実装しています。

ユーザー定義のクラスがThrowableインターフェースを直接実装することはできません。独自の例外を作る場合は、ExceptionクラスかErrorクラスを継承します。

Errorクラス

Errorクラスは、PHP実行時に発生する全ての内部エラーの基底クラスです。Exceptionクラスとの違いは、プログラムで対処できるかどうかであり、後続処理を続行できない致命的なエラーがErrorクラスとなります。

Throwableインターフェースを実装したクラスの関連図

[実装例]独自エラーを発生させてThrowableインターフェースでキャッチする

コード

class TestError extends Error {}

try {
    throw new TestError('Error');
} catch(Throwable $e) {
    echo 'catch ', get_class($e), "\n";
    echo $e->getMessage(), "\n";
}

実行結果

$ php test_error.php
catch TestError
Error

コメント

このブログの人気の投稿

docker-compose up で proxyconnect tcp: dial tcp: lookup proxy.example.com: no such host

docker-compose で起動したweb、MySQLに接続できない事象

【PHP】PHP_CodeSnifferを使う(コーディングルールのカスタマイズ)