74

あなたの意見では、エラーを処理している可能性があるのに、@演算子を使用してPHPのエラー/警告を抑制することは有効ですか?

もしそうなら、どのような状況でこれを使用しますか?

コード例は大歓迎です。

編集:返信者への注意。エラー報告をオフにするつもりはありませんが、たとえば、一般的な方法は

@fopen($file);

その後チェックします...しかし、@を実行することで取り除くことができます

if (file_exists($file))
{
    fopen($file);
}
else
{
    die('File not found');
}

または類似。

質問は、@がエラーを抑制するために使用され、他の方法で処理できない場所はありますか?

4

19 に答える 19

125

注:最初に、PHP開発者の99%がエラー抑制演算子を使用していることを認識しています(私は以前はその1つでした)。したがって、これを見るPHP開発者は同意しないと予想しています。

あなたの意見では、エラーを処理している可能性があるのに、@演算子を使用してPHPのエラー/警告を抑制することは有効ですか?

簡単な答え:
いいえ!

もっと長く正解:
すべてを知っているわけではないのでわかりませんが、これまでのところ、それが良い解決策であるという状況に遭遇したことはありません。

なぜ悪いのか:
PHPを使用して約7年になると、エラー抑制演算子によって引き起こされるデバッグの苦痛が際限なく見られ、避けられない状況に遭遇したことはありません。

問題は、エラーを抑制しているコードの一部が、現在表示されているエラーのみを引き起こす可能性があることです。ただし、抑制された行が依存するコード、またはそれが実行される環境を変更すると、その行が無視しようとしていたものとはまったく異なるエラーを出力しようとする可能性があります。次に、出力されていないエラーをどのように追跡しますか?地獄のデバッグへようこそ!

エラーが抑制されたために、2、3か月ごとにどれだけの時間を浪費していたかを理解するのに何年もかかりました。ほとんどの場合(ただし排他的ではありません)、これは開発者環境でエラーのないサードパーティのスクリプト/アプリ/ライブラリをインストールした後ですが、phpまたはサーバーの構成の違い、または通常はすぐにエラーを出力する依存関係の欠落のために私のものではありません問題が何であったかを警告しますが、開発者が魔法の@を追加したときは警告しません。

代替案(状況と望ましい結果に応じて):
認識している実際のエラーを処理して、コードの一部が特定のエラーを引き起こす場合、その特定の状況で実行されないようにします。しかし、あなたはこの部分を理解していると思います。エンドユーザーにエラーが表示されるのではないかと心配していました。これについては、これから説明します。

通常のエラーの場合は、ページを表示しているときに希望どおりに出力されるようにエラーハンドラーを設定できますが、エンドユーザーには表示されず、ログに記録されるため、ユーザーがトリガーしているエラーを把握できます。

php.iniで致命的なエラーdisplay_errorsがオフに設定されている場合(エラーハンドラーは引き続きトリガーされます)、エラーログを有効にします。開発サーバーとライブサーバー(推奨)がある場合は、開発サーバーでこの手順を実行する必要がないため、エラーログファイルを確認しなくても、これらの致命的なエラーをデバッグできます。シャットダウン機能を使用して大量の致命的なエラーをエラーハンドラに送信するトリックもあります。

要約:
それを避けてください。それには十分な理由があるかもしれませんが、まだ見たことがないので、その日まで、(@)エラー抑制演算子は悪だと思います。

詳細が必要な場合は、PHPマニュアルのエラー制御演算子ページで私のコメントを読むことができます。

于 2009-06-06T18:47:48.237 に答える
26

エラーを抑制して処理します。そうしないと、TOCTOUの問題が発生する可能性があります(チェック時間、使用時間。たとえば、file_existsがtrueを返した後、fopenの前にファイルが削除される可能性があります)。

しかし、私はエラーを抑制してそれらをなくすだけではありません。これらはよりよく見える。

于 2008-09-26T07:11:09.597 に答える
22

はい抑制は理にかなっています。

たとえば、ファイルを開くことができない場合、fopen()コマンドは戻ります。FALSEそれは問題ありませんが、PHP警告メッセージも生成します。多くの場合、警告は必要ありません。自分で確認しFALSEます。

実際、PHPマニュアルでは、この場合は@を使用することを具体的に提案しています。

于 2008-09-25T23:39:33.940 に答える
13

fopen()などの関数を使用するときに警告をスローしたくない場合は、エラーを抑制できますが、例外を使用します。

try {
    if (($fp = @fopen($filename, "r")) == false) {
        throw new Exception;
    } else {
        do_file_stuff();
    }
} catch (Exception $e) {
    handle_exception();
}
于 2008-09-26T04:07:41.563 に答える
7

すべての条件を処理できることがわかっている場合を除いて、エラー抑制は回避する必要があります。

これは、最初に見たよりもはるかに難しいかもしれません。

あなたが本当にすべきことは、エラーを報告するためにページを表示しているユーザーに頼ることができないので、あなたの報告方法としてphpの「error_log」に頼ることです。(また、phpがこれらのエラーを表示しないようにする必要があります)

そうすれば、少なくとも、システムで問題が発生しているすべてのことについての包括的なレポートが得られます。

本当にエラーを処理する必要がある場合は、カスタムエラーハンドラーを作成できます

http://php.net/set-error-handler

次に、例外(処理可能)を送信し、管理者に奇妙なエラーを報告するために必要なことを何でも行うことができます。

于 2008-09-25T23:51:46.813 に答える
7

「@」... ピリオドを使用することは決して許可しません。

コード内で '@' の使用を発見した場合は、コメントを追加して、使用箇所とそれが使用されている関数の周りの docblock の両方で、それが明白になるようにします。私も、この種のエラー抑制による「幽霊を追いかける」デバッグに噛まれたことがあります。見つけたときにその使用法を強調することで、次の人が簡単になることを願っています。

ネイティブ PHP 関数でエラーが発生した場合に独自のコードで例外をスローするようにしたい場合、'@' を使用するのが簡単だと思われる場合は、代わりに同じ結果が得られる別の方法を選択します。 (再び)コードで明らかに明らかです:

$orig = error_reporting(); // capture original error level
error_reporting(0);        // suppress all errors
$result = native_func();   // native_func() is expected to return FALSE when it errors
error_reporting($orig);    // restore error reporting to its original level
if (false === $result) { throw new Exception('native_func() failed'); }

それはただ書くだけのより多くのコードです:

$result = @native_func();

しかし、私に続く貧弱なデバッグ魂のために、私は抑制の必要性を非常に明白にすることを好みます。

于 2009-07-15T20:51:08.417 に答える
5

ほとんどの人は、エラー メッセージの意味を理解していません。
冗談じゃない。それらのほとんど。

彼らは、エラー メッセージはすべて同じだと思っており、「問題が発生しました!」と言っています。
彼らはそれを読もうとはしません。
エラーメッセージの最も重要な部分ですが、発生したという事実だけでなく、意味もあります。が問題なのかを教えてくれます。エラー メッセージはヘルプ用であり、「非表示にする方法」に煩わされるためのものではありません。問題。これは、初心者の Web プログラミングの世界における最大の誤解の 1 つです。

したがって、エラーメッセージを吐き出す代わりに、その内容を読む必要があります。「ファイルが見つかりません」という値は 1 つだけではありません。permission deniedsave mode restrictionなど、何千もの異なるエラーが発生する可能性がありますopen_basedir restriction。それぞれに適切なアクションが必要です。しかし、ギャグをすると、何が起こったのかわかりません。

OPはエラー処理でエラー報告を台無しにしていますが、それは非常に大きな違いです! エラー処理はユーザー向けです。ここでは「何かが起こった」で十分です。 エラー報告は、確かに何が起こったのかを必死に知る必要があるプログラマー向けです。

したがって、決してエラーメッセージをギャグしないでください。どちらもプログラマーのためにログに記録し、ユーザーのために処理します。

于 2010-10-06T08:12:34.747 に答える
3

私が本当にそれを使う必要があった唯一の場所はeval関数です。evalの問題は、構文エラーのために文字列を解析できない場合、evalはfalseを返さず、通常のスクリプトで解析エラーが発生するのと同じようにエラーをスローすることです。文字列に格納されているスクリプトが解析可能かどうかを確認するには、次のようなものを使用できます。

$script_ok = @eval('return true; '.$script);

AFAIK、これはこれを行うための最もエレガントな方法です。

于 2009-07-21T00:12:16.617 に答える
3

私が使用する場所の 1 つはソケット コードです。たとえば、タイムアウトが設定されている場合、@ を含めないと、パケットを取得しないことは有効ですが、これに関する警告が表示されます。

$data_len = @socket_recvfrom( $sock, $buffer, 512, 0, $remote_host, $remote_port )
于 2008-09-26T01:22:50.603 に答える
3

@ を使用すると、逆効果になる場合があります。私の経験では、常に php.ini または呼び出しでエラー報告をオフにする必要があります。

error_reporting(0);

生産現場で。このようにして、開発中に行をコメントアウトして、デバッグ用にエラーを表示しておくことができます。

于 2008-09-26T00:03:14.273 に答える
3

php.ini の警告とエラーを抑制する方法はありませんか? その場合、どの @ が問題を隠しているかを発見しようとせずに、フラグを変更するだけでデバッグできます。

于 2008-09-25T23:45:49.353 に答える
1

スクリプトの速度が低下するため、すべてを抑制したくはありません。

そして、はい、php.iniとスクリプトの両方でエラーを削除する方法があります(ただし、これは、ライブ環境にいて、phpからエラーをログに記録する場合にのみ実行してください)

<?php
    error_reporting(0);
?>

そして、あなたはそれをオフにするphp.iniバージョンのためにこれを読むことができます。

于 2008-09-25T23:48:30.720 に答える
0

カスタム エラー処理関数を使用していて、エラー (おそらく既知のエラー) を抑制したい場合は、このメソッドを使用します。エラーハンドラーが設定されている場合、エラーを抑制しないため、このコンテキストでは「@」の使用はお勧めできません。

3 つの関数を記述し、このように呼び出します。

# supress error for this statement
supress_error_start();  
$mail_sent = mail($EmailTo, $Subject, $message,$headers);
supress_error_end(); #Don't forgot to call this to restore error.  

function supress_error_start(){
    set_error_handler('nothing');
    error_reporting(0);
}

function supress_error_end(){
    set_error_handler('my_err_handler');
    error_reporting('Set this to a value of your choice');
}

function nothing(){ #Empty function
}

function my_err_handler('arguments will come here'){
      //Your own error handling routines will come here
}
于 2010-02-16T11:18:47.060 に答える
-1

DOMDocumentオブジェクトとして処理するためにHTMLファイルをロードしようとするときに使用します。HTMLに問題がある場合...そしてどのWebサイトに少なくとも1つがない場合...DOMDocument->loadHTMLFile()は、@で抑制しないとエラーをスローします。これが、PHPでHTMLスクレーパーを作成することに成功した唯一の方法です(おそらくもっと良い方法があります)。

于 2008-09-25T23:52:48.993 に答える