PHPはエラーなどのログが出そうなところで@演算子を使うと、出力を抑えることができます。でも使ってはいけません。
PHPを使い始めて10年以上経ちますが、1回も使ったことがないし実際コードで見たこともありません。
というか、こういうのがあるのすら忘れてた。
知らないのは非常識か? 使用不可が常識か?
プログラミングでのログ出力は、本来の処理とは関係ないもので暴論を言えばいらないです。じっさいスケジュールが詰まってくると、『そのへんは置いといて動くもの作って!』と言われることもあります。
これを言われると、エンジニアは地獄の入り口が見えるのでやりたくないんですが、置いといたままお役御免なんてこともしばしば。
仕事でプログラムを読むときソースコードのレベルが低いことがよくあります。でもプログラマのレベルが低いとはかぎりません。そのプログラマが納得してないこともあるから。
こういうことは良くあるので、ログ処理が中途半端なことが多々あります。
エラー制御演算子(@)は、意図的にログ出力を抑制するものです。外部要因でしぶしぶじゃなくて、わざと出さないもの。
冒頭で忘れてたというのは、ログをわざと出さないことはしないから。自分の首を絞めるようなもの。
使いみちがあるとすれば...
ログは開発時や保守・メンテのときに力を発揮します。トラブルを素早く対応するには絶対に必要なもの。それを出さないなんてリスクでしか無い。
想像ですが、『ログがユーザーに見えている。処理自体に問題はない。とりあえず消せ!』というとき、一番手っ取り早い方法で使うんでしょう。
ただこれは問題の解決になってないし多用されると本当に困ります。
使ってはいけないと言いましたが使ってもいいです。ただし、あとで必ず外してソースに残さないという前提で。
とりあえず暫定措置で@演算子を使い、根本解決をして終わったら外すという使い方。
エラーを抑制できるのは式だけ
エラー制御演算子の@の使い方はかんたんです。式だけに付けることができます。サンプルコードで見てみましょう。
変数
同じ変数で片方だけに@を付けてログの抑制を確認します。
<?php
$arr[$key];
@$arr[$key];
php error-control-operator-variable.php
PHP Notice: Undefined variable: arr in /home/.../error-control-operator-variable.php on line 3
PHP Notice: Undefined variable: key in /home/.../error-control-operator-variable.php on line 3
PHP Notice: Trying to access array offset on value of type null in /home/.../error-control-operator-variable.php on line 3
2行分の通知ログがあるはずですが、4行目は抑制されて出ません。
関数
まずは標準関数につけてみます。
<?php
@file('test.txt');
file('test.txt')
php error-control-operator-function-1.php
PHP Warning: file(test.txt): failed to open stream: No such file or directory in /home/.../error-control-operator-function-1.php on line 4
今度は自作関数で実行してみます。ログレベルをエラーに上げて見るために、まずは@を使わないところから。
<?php
function test($msg)
{
trigger_error('test() error', E_USER_ERROR);
}
test('first');
echo '----- end -----';
php error-control-operator-function-2.php
PHP Fatal error: test() error in /home/.../error-control-operator-function-2.php on line 5
これに@を使ってみましょう。
<?php
function test($msg)
{
trigger_error('test() error', E_USER_ERROR);
}
@test('first');
echo '----- end -----';
php error-control-operator-function-2.php
ね? ヤバいでしょ? 致命的なエラーになって処理が途中で終わっているのに、何が起きているのかさっぱり分かりません。
この仕様はPHP8では修正されています。PHP8では、Fatal Errorは@を付けてもログを出すようになっています。
今度は未定義の関数で実行してみます。
<?php
@test('first')
php error-control-operator-function-3.php
PHP Fatal error: Uncaught Error: Call to undefined function test() in /home/.../error-control-operator-function-3.php:3
Stack trace:
#0 {main}
thrown in /home/.../error-control-operator-function-3.php on line 3
未定義の関数はログが出ました。理由は正確には例外エラーだから。Exceptionを継承した例外クラスがスローするログは@を付けても出力されます。
(PHP8より前でも。このサンプルはPHP7で実行。)
クラス
クラスオブジェクトで見てみましょう。クラスではエラーは例外を使うのがスタンダードなので、基本的には@演算子は効きません。
<?php
class Test
{
function __construct($msg)
{
throw new Exception('constcut failed');
}
}
@(new Test('test1'));
インスタンス生成ではnewの前に@を付けます。クラス名の前につけるとシンタックスエラーになるので注意。
php error-control-operator-class-1.php
PHP Fatal error: Uncaught Exception: constcut failed in /home/.../error-control-operator-class-1.php:7
Stack trace:
#0 /home/.../error-control-operator-class-1.php(11): Test->__construct()
#1 {main}
thrown in /home/.../error-control-operator-class-1.php on line 7
今度はクラスの中で、ログ出力をしてみます。エラーログを使う人はいないので(例外を使う。)、警告を出してみます。
<?php
class Test
{
function __construct($msg)
{
trigger_error('test() parameter failed [' . $msg . ']', E_USER_WARNING)
}
}
new Test('test1');
echo 'process continue...' . PHP_EOL
php error-control-operator-class-2.php
PHP Warning: test() parameter failed [test1] in /home/.../error-control-operator-class-2.php on line 7
process continue...
警告なので処理は続行します。@演算子を付けてみます。
<?php
// 省略...
@new Test('test1');
echo 'process continue...' . PHP_EOL
php error-control-operator-class-2.php
process continue...
ログ抑制はできましたが、何が起きているのかさっぱり分かりません。
ダイレクトにログ抑制
最後に、trigger_error()に直接@を付けます。もちろんこれでも抑制ができます。
<?php
trigger_error('1', E_USER_DEPRECATED);
@trigger_error('2', E_USER_DEPRECATED);
trigger_error('1', E_USER_NOTICE);
@trigger_error('2', E_USER_NOTICE);
trigger_error('1', E_USER_WARNING);
@trigger_error('2', E_USER_WARNING);
@trigger_error('1', E_USER_ERROR)
php error-control-operator-trigger-error.php
PHP Deprecated: 1 in /home/.../error-control-operator-trigger-error.php on line 3
PHP Notice: 1 in /home/.../error-control-operator-trigger-error.php on line 6
PHP Warning: 1 in /home/.../error-control-operator-trigger-error.php on line 9
@演算子がついた '2' だけが抑制されているのが分かります。