66

カスタムエラーハンドラを使用して、解析エラーと致命的なエラーを処理するにはどうすればよいですか?

4

6 に答える 6

81

実際には、解析エラーと致命的なエラーを処理できます。set_error_handler()で定義したエラーハンドラ関数が呼び出されないのは事実です。これを行う方法は、register_shutdown_function()を使用してシャットダウン関数を定義することです。これが私のウェブサイトで働いていることです:

ファイルprepend.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()によって処理されます。

これは私が開発中のサイトで動作しています。私はまだ本番環境でそれをテストしていません。しかし、現在、開発中に見つけたすべてのエラーをキャッチしています。

同じエラーを各関数で1回ずつ、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エラーメッセージが表示されるリスクを減らします。

これが誰かに役立つことを願っています。

于 2011-09-06T00:29:44.103 に答える
31

簡単な答え:できません。マニュアルを参照してください:

次のエラータイプは、ユーザー定義関数では処理できません:E_ERROR、E_PARSE、E_CORE_ERROR、E_CORE_WARNING、E_COMPILE_ERROR、E_COMPILE_WARNING、およびset_error_handler()が呼び出されたファイルで発生したほとんどのE_STRICT。

他のすべてのエラーについては、次を使用できますset_error_handler()

編集:

このトピックについては、の使用に関していくつかの議論があるように思われるので、register_shutdown_function処理の定義を確認する必要があります。私にとって、エラーの処理とは、エラーをキャッチし、「適切な」方法で対応することを意味します。ユーザー基礎となるデータ(データベース、ファイル、Webサービスなど)。

を使用register_shutdown_functionすると、呼び出されたコード内からエラーを処理できません。つまり、エラーが発生した時点でコードが機能しなくなります。ただし、ホワイトページの代わりにエラーメッセージをユーザーに表示することはできますが、たとえば、失敗する前にコードが行ったことをロールバックすることはできません。

于 2009-12-14T10:59:58.147 に答える
31

次のようなコードを使用して、これらのエラーを追跡できます。

(解析エラーは、またはを介して他のスクリプトファイルで発生した場合、または他の回答で言及されているようにこのコードをに挿入した場合にのみキャッチできます。)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');
于 2009-12-14T11:08:24.577 に答える
13

ページhttp://www.php.net/manual/en/function.set-error-handler.phpのPHP.netコメントから

ここで、解析エラー(タイプ4、E_PARSE)をキャプチャできないと述べた人が何人かいることに気づきました。本当じゃない。これが私のやり方です。これが誰かに役立つことを願っています。

1)Webルートに「auto_prepend.php」ファイルを作成し、これを追加します。

<?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_valueauto_prepend_file/www/auto_prepend.php」をWebルートの.htaccessファイルに追加します。

  • メールアドレスとファイルへのパスを必ず変更してください。
于 2011-06-10T02:58:08.260 に答える
6

私の経験から、すべてのタイプのエラーをキャッチし、デフォルトのエラーメッセージを非表示にして、独自のエラーメッセージを表示することができます(必要に応じて)。以下に必要なものを示します。

index.php1)初期/トップレベルのスクリプト。カスタムエラーハンドラ関数を格納する場所で呼び出します。カスタムエラー関数ハンドラーは、その下にあるエラーをキャッチできるように、一番上にとどまる必要があります。つまり、含まれるファイルの「下」を意味します。

2)このトップスクリプトにエラーがないという仮定は真実でなければなりません!index.phpこれは非常に重要です。カスタムエラーハンドラ関数がで見つかった場合、致命的なエラーをキャッチすることはできませんindex.php

3)Phpディレクティブ(にある必要がありますindex.phpset_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');
于 2013-12-28T00:49:23.607 に答える
4

解析エラーのあるスクリプトは常に中断され、処理できません。したがって、スクリプトが直接またはinclude / requireによって呼び出された場合、何もできません。ただし、AJAX、フラッシュ、またはその他の方法で呼び出された場合、解析エラーを検出するための回避策があります。

swfuploadスクリプトを処理するためにこれが必要でした。Swfuploadは、ファイルのアップロードを処理するフラッシュであり、ファイルがアップロードされるたびに、PHP処理スクリプトを呼び出してfiledataを処理しますが、ブラウザー出力がないため、PHP処理スクリプトはデバッグのために次の設定を必要とします。

  • 警告と通知ob_start(); 最初に、ob_get_contents();によってコンテンツをセッションに保存します。処理スクリプトの最後:これは、別のスクリプトによってブラウザに表示できます
  • 上記と同じトリックでセッションを設定するための致命的なエラーregister_shutdown_function()
  • ob_get_contents()が処理スクリプトの最後にあり、解析エラーが以前に発生した場合、エラーを解析します。セッションは満たされません(nullです)デバッグスクリプトは、次のように処理できます。if(!isset($_SESSION["swfupload"])) echo "parse error";

1nullis not setisset()

于 2010-09-02T07:36:44.320 に答える