[PHP] @でエラーを回避するのはやめよう

えと、今さら感のある記事になってしまいますが・・・
他の記事を書いていたら副産物としてできてしまったので、書いておこうと思います。

エラー対策として、@ を使いたくなるかもしれません。

if ($fp = fopen("hoge.txt", "r")){
if ($fp = @fopen("hoge.txt", "r")){

この例では、fopenで、hoge.txtを開こうとしています。
1行目では、hoge.txtが存在しなければエラーが発生し、処理が中断し、エラー内容がブラウザに表示されてしまいます。
そこで、2行目のように書くことで、エラーを抑制することが可能なのですが・・・
実は、この @ が曲者で、非常に重い処理なんです。
ということで、 @ を使用するのはやめましょう。

・・・で、何を根拠に?という方は、実際にテストすることをオススメします。

下記がテストコード。説明はコードの下に続きます。

<?php
error_reporting(E_NOTICE);

// この数字をPCのスペックに合わせて大きくしてください
$LoopCount = 10000;

// @でエラー制御
$Start = getMicrotime();
for ($i = 0; $i < $LoopCount; $i++){
$hoge = @$fuga["fuga"];
}
echo '@有: ' . ($End1 = (getMicrotime() - $Start)) . '秒<hr />';

// 事前チェック方式
$Start = getMicrotime();
for ($i = 0; $i &lt; $LoopCount; $i++){
if ( isset( $fuga[&quot;fuga&quot;] ) ){ // 変数がセットされているか確認
$hoge = $fuga[&quot;fuga&quot;]; // ↑がfalseなのでここは通らない
}
}
echo '事前: ' . ($End2 = (getMicrotime() - $Start)) . '秒<hr />';

echo '事前チェック方式が ' . ($End1 / $End2) . ' 倍早い';

// 現在のマイクロ秒を取得
function getMicrotime(){
list($msec, $sec) = explode(" ", microtime());
return ((float)$sec + (float)$msec);
}
?&gt;

実行結果を見る

このテストコードの意味としては、事前に何もセットされていない $fuga["fuga"]; が突然現れて、しかもその値を$hogeに代入させようとしてしまった時のエラーです。

isset() は、引数の変数がセットされていればtrueを返します。
このように事前に値をチェックすることで、エラーを回避することができます。

最初に書いた、@fopen の場合ですと、事前にファイルが存在するか確認し、存在する場合だけfopenするように書き換えることができます。

if (file_exists("hoge.txt")){ // ファイルの存在確認
if ($fp = fopen("hoge.txt", "r")){