PHP:カスタム エラー ハンドラー - 解析エラーと致命的なエラーの処理
-
19-09-2019 - |
質問
どうすればよいでしょうか 解析する & 致命的 を使用したエラー カスタム エラーハンドラ?
解決
簡単な答え:あなたはできません。を参照してください。 マニュアル:
次のエラータイプは、ユーザー定義の関数では処理できません。e_error、e_parse、e_core_error、e_core_warning、e_compile_error、e_compile_warning、およびe_strictの大部分は、set_error_handler()が呼び出されるファイルで提起されました。
他のすべてのエラーについては、次を使用できます set_error_handler()
編集:
このトピックについては、使用に関していくつかの議論があるようですので、 register_shutdown_function
, 、処理の定義を見てみましょう。私にとって、エラーの処理とは、エラーをキャッチし、ユーザーにとって「適切な」方法で対応することを意味します。 そして 基礎となるデータ (データベース、ファイル、Web サービスなど)。
使用する register_shutdown_function
エラーが呼び出されたコード内からエラーを処理することはできません。つまり、コードはエラーが発生した時点で動作を停止したままになります。ただし、白いページの代わりにエラー メッセージをユーザーに表示することはできますが、たとえば、コードが失敗する前に実行したことをロールバックすることはできません。
他のヒント
実際には、解析エラーや致命的なエラーを処理できます。確かに、set_error_handler() で定義したエラー ハンドラー関数は呼び出されません。これを行う方法は、 register_shutdown_function() でシャットダウン関数を定義することです。私のウェブサイトで取り組んでいることは次のとおりです。
ファイル 先頭に追加.php (このファイルはすべての PHP スクリプトの先頭に自動的に追加されます)。PHP にファイルを先頭に追加する場合のヒントについては、以下を参照してください。
set_error_handler("errorHandler");
register_shutdown_function("shutdownHandler");
function errorHandler($error_level, $error_message, $error_file, $error_line, $error_context)
{
$error = "lvl: " . $error_level . " | msg:" . $error_message . " | file:" . $error_file . " | ln:" . $error_line;
switch ($error_level) {
case E_ERROR:
case E_CORE_ERROR:
case E_COMPILE_ERROR:
case E_PARSE:
mylog($error, "fatal");
break;
case E_USER_ERROR:
case E_RECOVERABLE_ERROR:
mylog($error, "error");
break;
case E_WARNING:
case E_CORE_WARNING:
case E_COMPILE_WARNING:
case E_USER_WARNING:
mylog($error, "warn");
break;
case E_NOTICE:
case E_USER_NOTICE:
mylog($error, "info");
break;
case E_STRICT:
mylog($error, "debug");
break;
default:
mylog($error, "warn");
}
}
function shutdownHandler() //will be called when php script ends.
{
$lasterror = error_get_last();
switch ($lasterror['type'])
{
case E_ERROR:
case E_CORE_ERROR:
case E_COMPILE_ERROR:
case E_USER_ERROR:
case E_RECOVERABLE_ERROR:
case E_CORE_WARNING:
case E_COMPILE_WARNING:
case E_PARSE:
$error = "[SHUTDOWN] lvl:" . $lasterror['type'] . " | msg:" . $lasterror['message'] . " | file:" . $lasterror['file'] . " | ln:" . $lasterror['line'];
mylog($error, "fatal");
}
}
function mylog($error, $errlvl)
{
...do whatever you want...
}
PHP は、スクリプトのいずれかでエラーを検出した場合、関数 errorHandler() を呼び出します。エラーによりスクリプトが即時にシャットダウンされる場合、エラーは関数 shutdownHandler() によって処理されます。
これは私が開発中のサイトで動作しています。まだ実稼働環境でテストしていません。しかし、現在、開発中に見つかったすべてのエラーをキャッチしています。
同じエラーが関数ごとに 2 回発生するリスクがあると思います。これは、shutdownHandler() 関数で処理しているエラーが errorHandler() 関数でもキャッチされた場合に発生する可能性があります。
TODO:
1 - エラーを適切に処理するには、より良い log() 関数に取り組む必要があります。私はまだ開発中であるため、基本的にエラーをデータベースに記録し、それを画面にエコー表示しています。
2 - すべての MySQL 呼び出しのエラー処理を実装します。
3 - JavaScript コードのエラー処理を実装します。
重要な注意事項:
1 - php.ini で次の行を使用して、上記のスクリプトをすべての php スクリプトの先頭に自動的に追加します。
auto_prepend_file = "/homepages/45/d301354504/htdocs/hmsee/cgi-bin/errorhandling.php"
それはうまくいきます。
2 - E_STRICT エラーを含むすべてのエラーをログに記録し、解決しています。私はクリーンなコードを開発することを信じています。開発中、php.ini ファイルには次の行が含まれています。
track_errors = 1
display_errors = 1
error_reporting = 2147483647
html_errors = 0
ライブに移行するときは、display_errors を 0 に変更して、ユーザーに見苦しい PHP エラー メッセージが表示されるリスクを軽減します。
これが誰かの役に立てば幸いです。
次のようなコードを使用して、これらのエラーを追跡できます。
(解析エラーは、次の場所で発生した場合にのみ捕捉できます。 他の スクリプトファイル経由 include()
または require()
, 、またはこのコードを auto_prepend_file
他の回答で述べたように。)
function shutdown() {
$isError = false;
if ($error = error_get_last()){
switch($error['type']){
case E_ERROR:
case E_CORE_ERROR:
case E_COMPILE_ERROR:
case E_USER_ERROR:
$isError = true;
break;
}
}
if ($isError){
var_dump ($error);//do whatever you need with it
}
}
register_shutdown_function('shutdown');
ページ上の PHP.net コメントより http://www.php.net/manual/en/function.set-error-handler.php
ここで何人かの人が、解析エラー (タイプ 4、E_PARSE) をキャプチャできないと述べていることに気付きました。本当じゃない。これが私のやり方です。これが誰かの役に立てば幸いです。
1) 「auto_prepend.php」ファイルを Web ルートに作成し、これを追加します。
<?php
register_shutdown_function('error_alert');
function error_alert()
{
if(is_null($e = error_get_last()) === false)
{
mail('your.email@example.com', 'Error from auto_prepend', print_r($e, true));
}
}
?>
2)次に、この「PHP_VALUE AUTO_PREND_FILE /WWW/AUTO_PREND.PHP」をWebルートの.htaccessファイルに追加します。
- 電子メール アドレスとファイルへのパスを必ず変更してください。
私の経験から言えば、あらゆる種類のエラーを捕捉し、デフォルトのエラー メッセージを非表示にし、(必要に応じて) 独自のエラー メッセージを表示することができます。以下に必要なものを列挙します。
1) 初期/トップレベルのスクリプトと呼びます。 index.php
カスタム エラー ハンドラー関数を保存する場所。カスタム エラー関数ハンドラーは、その下 (インクルード ファイル内での「下」という意味です) のエラーをキャッチできるように、先頭に配置する必要があります。
2) この先頭のスクリプトにはエラーがないという仮定は正しいに違いありません。これは非常に重要です。致命的なエラーをキャッチすることはできません。 index.php
カスタム エラー ハンドラー関数が次の場所で見つかった場合 index.php
.
3) Php ディレクティブ (次のディレクトリにもある必要があります) index.php
)
set_error_handler("myNonFatalErrorHandler");
#致命的ではないエラーをキャッチするためregister_shutdown_function('myShutdown');
#致命的なエラーをキャッチするためini_set('display_errors', false);
#PHPでユーザーに表示されるエラーを隠すためini_set('log_errors',FALSE);
#エラーを自分たちでログに記録すると仮定しますini_set('error_reporting', E_ALL);
#すべてのエラーを報告したいと考えています
本番中は(私が間違っていなければ)終了できます ini_set('error_reporting', E_ALL);
同時にエラーをログに記録できるようにするためにそのままにします ini_set('display_errors', false);
ユーザーにエラーが表示されないことを確認します。
私が話している2つの機能の実際の内容としては、 myNonFatalErrorHandler
そして myShutdown
, 話をシンプルにするために、ここでは詳細な内容は記載しません。さらに、他の訪問者は多くの例を示しました。私は非常に単純なアイデアを示しているだけです。
function myNonFatalErrorHandler($v, $m, $f, $l, $c){
$some_logging_var_arr1[]="format $v, $m, $f, ".$err_lvl[$l].", $c the way you like";
//You can display the content of $some_logging_var_arr1 at the end of execution too.
}
function myShutdown()
{
if( ($e=error_get_last())!==null ){
$some_logging_var_arr2= "Format the way you like:". $err_level[$e['type']].$e['message'].$e['file'].$e['line'];
}
//display $some_logging_var_arr2 now or later, e.g. from a custom session close function
}
$err_lvl の場合は次のようになります。
$err_lvl = array(E_ERROR=>'E_ERROR', E_CORE_ERROR=>'E_CORE_ERROR', E_COMPILE_ERROR=>'E_COMPILE_ERROR', E_USER_ERROR=>'E_USER_ERROR', E_PARSE=>'E_PARSE', E_RECOVERABLE_ERROR=>'E_RECOVERABLE_ERROR', E_WARNING=>'E_WARNING', E_CORE_WARNING=>'E_CORE_WARNING', E_COMPILE_WARNING=>'E_COMPILE_WARNING',
E_USER_WARNING=>'E_USER_WARNING', E_NOTICE=>'E_NOTICE', E_USER_NOTICE=>'E_USER_NOTICE',E_STRICT=>'E_STRICT');
解析エラーのあるスクリプトは常に中断され、処理できません。したがって、スクリプトが直接呼び出された場合、または include/require によって呼び出された場合、できることは何もありません。ただし、AJAX、フラッシュ、またはその他の方法で呼び出された場合は、 は 解析エラーを検出する方法の回避策。
これを処理する必要がありました swfアップロード 脚本。Swfupload はファイルのアップロードを処理するフラッシュであり、ファイルがアップロードされるたびに PHP 処理スクリプトを呼び出してファイルデータを処理します。ただし、ブラウザ出力はないため、PHP 処理スクリプトにはデバッグ目的で次の設定が必要です。
- 警告と通知 ob_start();最初に、ob_get_contents() によってコンテンツをセッションに保存します。処理スクリプトの最後に次のように記述します。これは別のスクリプトでブラウザに表示できます
- 致命的なエラー register_shutdown_function() を使用して、上記と同じトリックでセッションを設定します。
- 解析エラー ob_get_contents() が処理スクリプトの最後にあり、その前に解析エラーが発生した場合、セッションは埋まりません (null になります)。デバッグ スクリプトは次の方法でこれを処理できます。
if(!isset($_SESSION["swfupload"])) echo "parse error";
注1 null
手段 is not set
に isset()