关于操作符:PHP中@符号的用法是什么?

What is the use of the @ symbol in PHP?

我已经看到在某些功能前面使用@,如下所示:

1
$fileHandle = @fopen($fileName, $writeAttributes);

这个符号的用途是什么?


它会抑制错误消息-请参阅PHP手册中的错误控制操作符。


它抑制错误。

参见手册中的错误控制操作员:

PHP supports one error control operator: the at sign (@). When prepended to an expression in PHP, any error messages that might be generated by that expression will be ignored.

If you have set a custom error handler function with set_error_handler() then it will still get called, but this custom error handler can (and should) call error_reporting() which will return 0 when the call that triggered the error was preceded by an @...


@符号是错误控制操作员(也称为"静默"或"关闭"操作员)。它使PHP禁止关联表达式生成的任何错误消息(通知、警告、致命错误等)。它就像一元运算符一样工作,例如,它具有优先级和关联性。以下是一些例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@echo 1 / 0;
// generates"Parse error: syntax error, unexpected T_ECHO" since
// echo is not an expression

echo @(1 / 0);
// suppressed"Warning: Division by zero"

@$i / 0;
// suppressed"Notice: Undefined variable: i"
// displayed"Warning: Division by zero"

@($i / 0);
// suppressed"Notice: Undefined variable: i"
// suppressed"Warning: Division by zero"

$c = @$_POST["a"] + @$_POST["b"];
// suppressed"Notice: Undefined index: a"
// suppressed"Notice: Undefined index: b"

$c = @foobar();
echo"Script was not terminated";
// suppressed"Fatal error: Call to undefined function foobar()"
// however, PHP did not"ignore" the error and terminated the
// script because the error was"fatal"

如果使用自定义错误处理程序而不是标准的PHP错误处理程序,会发生什么情况:

If you have set a custom error handler function with
set_error_handler() then it will still get called, but this custom
error handler can (and should) call error_reporting() which will
return 0 when the call that triggered the error was preceded by an @.

下面的代码示例说明了这一点:

1
2
3
4
5
6
7
function bad_error_handler($errno, $errstr, $errfile, $errline, $errcontext) {
    echo"[bad_error_handler]: $errstr";
    return true;
}
set_error_handler("bad_error_handler");
echo @(1 / 0);
// prints"[bad_error_handler]: Division by zero"

错误处理程序没有检查@符号是否有效。手册建议如下:

1
2
3
4
5
6
7
function better_error_handler($errno, $errstr, $errfile, $errline, $errcontext) {
    if(error_reporting() !== 0) {
        echo"[better_error_handler]: $errstr";
    }
    // take appropriate action
    return true;
}

还要注意,尽管隐藏了错误,任何自定义错误处理程序(用set_error_handler设置)仍将被执行!


就像前面已经回答过的那样:@操作符禁止php中的所有错误,包括通知、警告甚至严重错误。

但是:请不要使用@操作符。

为什么?

好吧,因为当您使用@操作符进行错误抑制时,您根本不知道在发生错误时从何处开始。我已经对一些开发人员经常使用@操作符的遗留代码有了一些"乐趣"。尤其是在文件操作、网络调用等情况下,许多开发人员都建议使用@操作符,因为在这里发生错误时,有时会超出范围(例如,第三方API可能无法访问等)。

但不使用它有什么意义呢?让我们从两个角度来看看:

作为开发人员:当使用@时,我完全不知道从哪里开始。如果有成百上千的函数调用使用@,那么错误可能与everywhare类似。在这种情况下,无法进行合理的调试。即使这只是第三方的失误,那也很好,而且你做得很快。;-)此外,最好在错误日志中添加足够的详细信息,这样开发人员就可以轻松地决定日志条目是必须进一步检查的内容,还是仅仅是第三方失败超出了开发人员的范围。

作为用户:用户根本不关心错误的原因是什么。软件可以让他们工作,完成一项特定的任务,等等。他们不在乎是开发人员的错还是第三方的问题。特别是对于用户,我强烈建议记录所有错误,即使它们超出范围。也许你会注意到一个特定的API经常离线。你能做什么?你可以和你的API合作伙伴交谈,如果他们不能保持稳定,你应该寻找另一个合作伙伴。

简言之:你应该知道存在类似于@的东西(知识总是很好的),但不要使用它。许多开发人员(尤其是那些从其他人那里调试代码的开发人员)将非常感激。


假设我们没有使用"@"运算符,那么我们的代码如下所示:

1
$fileHandle = fopen($fileName, $writeAttributes);

如果我们试图打开的文件找不到怎么办?它将显示一条错误消息。

要抑制错误消息,我们使用"@"运算符,如下所示:

1
$fileHandle = @fopen($fileName, $writeAttributes);


如果打开失败,将生成E级警告错误。您可以使用@取消此警告。


@抑制错误信息。

它用于以下代码段:

1
@file_get_contents('http://www.exaple.com');

如果域"http://www.example.com"不可访问,将显示一个错误,但是对于@没有显示任何内容。


@抑制函数抛出的错误消息。fopen在文件不退出时抛出错误。@符号使执行移到下一行,即使文件不存在。我的建议是,在开发PHP代码时,不要在本地环境中使用它。


值得一提的是,在使用@You should be aware时,这里有一些指针,对于完整的运行视图,本文是:http://mstd.eu/index.php/2016/06/30/php-rapid-fire-what-is-the-symbol-used-for-in-php/

  • 即使预先准备了@symbol,错误处理程序仍将被激发,这仅仅意味着设置了0的错误级别,这将必须在自定义错误处理程序中得到适当的处理。

  • 在include前面加@会将include文件中的所有错误设置为错误级别0


  • PHP支持一个错误控制操作符:at符号(@)。在PHP中预先准备表达式时,该表达式可能生成的任何错误消息都将被忽略。

    如果使用set_error_handler()设置了一个自定义错误处理程序函数,那么它仍然会被调用,但是这个自定义错误处理程序可以(并且应该)调用error_reporting(),当触发错误的调用前面有@时,它将返回0

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <?php
    /* Intentional file error */
    $my_file = @file ('non_existent_file') or
        die ("Failed opening file: error was '$php_errormsg'");

    // this works for any expression, not just functions:
    $value = @$cache[$key];
    // will not issue a notice if the index $key doesn't exist.

    ?>

    注:

    1)@-运算符仅对表达式有效。

    2)一个简单的经验法则是:如果你能得到某个东西的值,你可以预先将@operator添加到它上面。例如,您可以将其前置到变量、函数和包含调用、常量等。不能将其前置到函数、类定义或条件结构(如if和foreach等)。

    警告:

    Currently the"@" error-control operator prefix will even disable
    error reporting for critical errors that will terminate script
    execution. Among other things, this means that if you use"@" to
    suppress errors from a certain function and either it isn't available
    or has been mistyped, the script will die right there with no
    indication as to why.