396

いくつかの php ネイティブ関数からスローされる警告をキャッチして、それらを処理する必要があります。

具体的には:

array dns_get_record  ( string $hostname  [, int $type= DNS_ANY  [, array &$authns  [, array &$addtl  ]]] )

DNS クエリが失敗すると、警告がスローされます。

try/catch警告は例外ではないため、機能しません。

私は今2つのオプションがあります:

  1. set_error_handlerページ内のすべての警告をフィルタリングするために使用する必要があるため、やり過ぎのように思えます (これは本当ですか?)。

  2. これらの警告が画面にエコーされないようにエラーの報告/表示を調整してから、戻り値を確認します。の場合false、ホスト名のレコードは見つかりません。

ここでのベストプラクティスは何ですか?

4

12 に答える 12

405

エラー ハンドラの設定と復元

1 つの可能性は、呼び出しの前に独自のエラー ハンドラーを設定し、後で を使用して以前のエラー ハンドラーを復元することrestore_error_handler()です。

set_error_handler(function() { /* ignore errors */ });
dns_get_record();
restore_error_handler();

このアイデアに基づいて、エラーをログに記録する再利用可能なエラー ハンドラーを作成できます。

set_error_handler([$logger, 'onSilencedError']);
dns_get_record();
restore_error_handler();

エラーを例外に変える

クラスを使用set_error_handler()して、ErrorExceptionすべての php エラーを例外に変えることができます。

set_error_handler(function($errno, $errstr, $errfile, $errline) {
    // error was suppressed with the @-operator
    if (0 === error_reporting()) {
        return false;
    }
    
    throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
});

try {
    dns_get_record();
} catch (ErrorException $e) {
    // ...
}

独自のエラー ハンドラーを使用する場合に注意すべき重要な点は、error_reporting設定をバイパスし、すべてのエラー (通知、警告など) をエラー ハンドラーに渡すことです。2 番目の引数を onset_error_handler()に設定して、受信するエラーの種類を定義するか... = error_reporting()、エラー ハンドラー内を使用して現在の設定にアクセスできます。

警告の抑制

dns_get_record()もう 1 つの可能性は、@ 演算子で呼び出しを抑制し、その後の戻り値を確認することです。ただし、エラー/警告は抑制されるのではなく、処理されるようにトリガーされるため、これに反対することをお勧めします。

于 2009-08-06T21:55:39.803 に答える
164

E_WARNING実際に機能する解決策は、次のようにパラメーターを使用して単純なエラーハンドラーを設定することであることが判明しました。

set_error_handler("warning_handler", E_WARNING);
dns_get_record(...)
restore_error_handler();

function warning_handler($errno, $errstr) { 
// do something
}
于 2012-06-26T11:21:44.913 に答える
31

@オペレーターには注意してください。警告を抑制しますが、致命的なエラーも抑制します。私は誰かが書いたシステムで問題をデバッグするのに多くの時間を費やしました、@mysql_query( '...' )そして問題はmysqlサポートがPHPにロードされなかったということでしたそしてそれはサイレント致命的なエラーを投げました。PHPコアの一部であるものは安全ですが、注意して使用してください

bob@mypc:~$ php -a
Interactive shell

php > echo @something(); // this will just silently die...

これ以上の出力はありません-これをデバッグして頑張ってください!

bob@mypc:~$ php -a
Interactive shell

php > echo something(); // lets try it again but don't suppress the error
PHP Fatal error:  Call to undefined function something() in php shell code on line 1
PHP Stack trace:
PHP   1. {main}() php shell code:0
bob@mypc:~$ 

今回は、失敗した理由を確認できます。

于 2011-08-10T02:43:27.753 に答える
5

警告を試行/キャッチしたかったのですが、同時に通常の警告/エラー ログ (例: /var/log/apache2/error.log) を保持しました。ハンドラーが返さなければならないものfalse。ただし、「throw new...」ステートメントは基本的に実行を中断するため、「wrap in function」トリックを実行する必要があります。これについては、以下でも説明しています。

PHPで例外をスローする静的な方法はありますか

または、簡単に言えば:

  function throwErrorException($errstr = null,$code = null, $errno = null, $errfile = null, $errline = null) {
    throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
  }
  function warning_handler($errno, $errstr, $errfile, $errline, array $errcontext) {
    return false && throwErrorException($errstr, 0, $errno, $errfile, $errline);
    # error_log("AAA"); # will never run after throw
    /* Do execute PHP internal error handler */
    # return false; # will never run after throw
  }
  ...
  set_error_handler('warning_handler', E_WARNING);
  ...
  try {
    mkdir($path, 0777, true);
  } catch (Exception $e) {
    echo $e->getMessage();
    // ...
  }

編集: 詳細な検査の後、動作しないことが判明しました: " return false && throwErrorException ..." は、基本的に、例外をスローせ、エラー ログに記録するだけです。false &&" " のように " " の部分を削除するreturn throwErrorException ...と、例外をスローするようになりますが、error_log には記録されません。

于 2013-12-27T12:37:23.953 に答える
4

これが唯一の解決策でない限り、通常は @ を使用しないでください。その特定のケースでは、関数 dns_check_record を最初に使用して、レコードが存在するかどうかを確認する必要があります。

于 2011-01-03T22:23:24.513 に答える
2

おそらく警告を完全に取り除こうとする必要がありますが、それが不可能な場合は、呼び出しの先頭に @ を追加し (つまり、@dns_get_record(...))、取得できる情報を使用して、警告が発生したかどうかを判断することができます。か否か。

于 2009-08-06T21:53:51.057 に答える
2

dns_get_record()失敗した場合は を返す必要FALSEがあるため、警告を抑制して@から戻り値を確認できます。

于 2009-08-06T21:58:19.720 に答える
-2

@ を使用して、単純な操作の場合にのみ警告を抑制することをお勧めします (例: $prop = @($high/($width - $depth)); ゼロ除算の警告をスキップする)。ただし、ほとんどの場合、処理する方が適切です。

于 2016-09-02T09:18:34.663 に答える