PHPでregister_shutdown_functionを使ってエラーハンドリングした場合にFatal errorを無視する場合がある

fatalerror プログラミング

PHPでFatal Errorsが起きた場合に画面が真っ白になるのを防ぐ手段としてregister_shutdown_functionを使う方法というのが一般的に使われています

~~~
//On production environments
error_reporting(0);

function fatalErrorHandler() {
# Getting last error
$error = error_get_last();
# Checking if last error is a fatal error
if(($error[‘type’] === E_ERROR) || ($error[‘type’] === E_USER_ERROR)|| ($error[‘type’] === E_USER_NOTICE)) {
# Here we handle the error, displaying HTML, logging, …
echo “ERRORnr : ” . $error[‘type’]. ” |Msg : “.$error[‘message’].” |File : “.$error[‘file’]. ” |Line : ” . $error[‘line’];
}else {
echo “no error where found ” ;

}
}

# Registering shutdown function
register_shutdown_function(‘fatalErrorHandler’);

// let force a Fatal error — function does not exist
functiontest();
~~~
引用元

これを実行すると画面上にエラーが表示されます
ERRORnr : 1 |Msg : Call to undefined function functiontest() |File : test.php |Line : 27

ところがこんなふうに書くとどうなると思いますか?

~~~

function fatalErrorHandler() {
# Getting last error
$error = error_get_last();
# Checking if last error is a fatal error
if(($error[‘type’] === E_ERROR) || ($error[‘type’] === E_USER_ERROR)|| ($error[‘type’] === E_USER_NOTICE)) {
# Here we handle the error, displaying HTML, logging, …
echo “ERRORnr : ” . $error[‘type’]. ” |Msg : “.$error[‘message’].” |File : “.$error[‘file’]. ” |Line : ” . $error[‘line’];
}else {
echo “no error where found ” ;

}
}

function functiontest() {
functiontest2();
}

# Registering shutdown function
register_shutdown_function(‘fatalErrorHandler’);

register_shutdown_function(‘functiontest’);

~~~

結果はno error where found と表示されます
functiontest2が存在しないことはなぜか無視されます

ちなみにini_set(‘display_errors’ , 1);すればFatal errorが表示されるが最後(functiontest2の前)まで実行されるという不思議な挙動になります
~~~
Fatal error: Call to undefined function functiontest2() in test.php on line 19
~~~

register_shutdown_functionは順番に実行されるのでこう書き換えると

~~~

function fatalErrorHandler() {
# Getting last error
$error = error_get_last();
# Checking if last error is a fatal error
if(($error[‘type’] === E_ERROR) || ($error[‘type’] === E_USER_ERROR)|| ($error[‘type’] === E_USER_NOTICE)) {
# Here we handle the error, displaying HTML, logging, …
echo “ERRORnr : ” . $error[‘type’]. ” |Msg : “.$error[‘message’].” |File : “.$error[‘file’]. ” |Line : ” . $error[‘line’];
}else {
echo “no error where found ” ;

}
}

function functiontest() {
functiontest2();
}

register_shutdown_function(‘functiontest’);
# Registering shutdown function
register_shutdown_function(‘fatalErrorHandler’);

echo 1;
~~~

echo 1 が出力されますが no error where found とは表示されなくなります
もちろんini_set(‘display_errors’ , 1);すればFatal errorが表示されます

わけがわかりませんね(゚∀゚)
知りたいのは書き換えた2つのようにエラーハンドリング以外の場合にregister_shutdown_functionを使ってFatal errorを取得してちゃんと想定通りの動きが出来るようになるのか?ということですが、出来るんですかね?

コメント

  1. ngyuki より:

    シャットダウン関数 functiontest で fatal error になったためその次に呼ばれるはずだったシャットダウン関数 fatalErrorHandler が呼ばれなかった、からだと思いますよ?

    register_shutdown_function はエラーハンドラを登録するのではなく、スクリプトの終了時に実行される関数を登録するもので、シャットダウン関数の中で fatal error が発生したり exit で終了したりすると後続のシャットダウン関数は実行されません。

    • のぶ より:

      公式サイトにも載っている書き方ですし、(http://php.net/manual/ja/function.register-shutdown-function.php#85727)、FuelPHP内でも使われているのでこの使い方どうなの?って思って書いたので、エラーハンドラとして使うべきではないということでいいんでしょうか?

タイトルとURLをコピーしました