【问题标题】:What is the use of the @ symbol in PHP?PHP中@符号的用途是什么?
【发布时间】:2024-01-24 02:26:02
【问题描述】:

我在某些函数前面看到过@ 的用法,如下所示:

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

这个符号有什么用?

【问题讨论】:

  • RichieHindle 和 Aiden Bell 都给出了正确答案,但由于我只能将一个答案设置为已接受,我将选择第一个。对不起艾登
  • 在维护代码库时抑制错误(虽然很好)可能会导致错误...*.com/a/7116175/282343

标签: php operators error-suppression


【解决方案1】:

它会抑制错误消息 - 请参阅 PHP 手册中的 Error Control Operators

【讨论】:

  • 这有点快!
  • 是的;降到第二!我必须检查 answer-id 看看谁先进来 :)
  • 我有时间在发布后更正我的压制拼写......并且该死的你同时使用链接进行了增强愤怒:P
  • 很酷的功能。它使isset()的使用变得不必要,以避免undefined offset错误。
【解决方案2】:

它抑制错误。

参见手册中的Error Control Operators

PHP 支持一种错误控制运算符:at 符号 (@)。当附加到 PHP 中的表达式时,该表达式可能生成的任何错误消息都将被忽略。

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

【讨论】:

  • 这个答案是第一个(根据谁先回答的上下文)。
【解决方案3】:

@ 符号是error control operator(又名“静音”或“闭嘴”运算符)。它使 PHP 抑制由相关表达式生成的任何错误消息(通知、警告、致命等)。它就像一元运算符一样工作,例如,它具有优先级和关联性。下面是一些例子:

@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 错误处理程序会发生什么:

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

以下代码示例对此进行了说明:

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"

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

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

【讨论】:

  • echo @(1 / 0); 给了我DivisionByZeroError 我正在使用 php 8。也许是因为 DivisionByZeroError 是在 PHP 7 中添加的?
  • @Omkar76 在编写此答案时,PHP5 中不存在此错误。 stfu 运算符的行为可能在 PHP8 中发生了变化。
  • 但是docs 说它是在 7 中添加的。我认为它曾经只是一个警告。现在它抛出异常。哪个@显然无法压制。
  • @Omkar76 该页面上的 cmets 似乎表明它不再是一个警告,而是一个例外......这超出了@ 运算符的分数。
【解决方案4】:

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

【讨论】:

    【解决方案5】:

    就像之前已经回答的那样:@ 运算符抑制 PHP 中的所有错误,包括通知、警告甚至严重错误。

    但是: 请不要使用@ 运算符。

    为什么?

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

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

    作为开发人员: 当使用@ 时,我完全不知道从哪里开始。如果有数百甚至数千个函数调用 @ 错误可能就像everyhwere。在这种情况下,不可能进行合理的调试。即使它只是一个 3rdparty 错误 - 那也很好,你很快就完成了。 ;-) 此外,最好在错误日志中添加足够的详细信息,以便开发人员能够轻松决定日志条目是必须进一步检查的内容,还是只是超出开发人员范围的第 3 方故障。

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

    简而言之:您应该知道存在类似@ 的东西(知识总是好的),但只是不要使用它。许多开发者(尤其是那些调试别人代码的)会非常感激的。

    【讨论】:

    • 某些警告只能使用 @ 可靠地抑制(例如 fopen(),其中任何预测结果的尝试都受制于竞争条件),如果您有代码来更整齐地处理错误条件那么使用@ 是正确的做法,这特别有用,特别是如果您没有将text/html(或类似的)返回给客户。 (可能返回 image/png 或 "json")
    • 你不应该压制警告——它们是在说你做错了什么。没有无法正确检查或处理状态的竞争条件。
    • 我的代码中有几个地方有以下内容。 if( session_status() == PHP_SESSION_NONE ) session_start();这是我继承的遗留应用程序,并且有多次调用设置脚本的地方,所以我必须测试。简单地使用@session_start(); 会有什么问题(如果有的话)?
    • @dtbarne 不,不是。 :-/ 我非常不同意。当然,在存在数组的子元素之前,您必须检查父项本身是否存在……这只是您正在做的事情,而且远非最佳实践。
    • 给我一个很好的理由,为什么添加 12 多行代码并且没有增加任何价值,但只会降低代码的可读性和简洁性,而不是你在某个地方读到它“很脏”也许你可以改变我的想法。
    【解决方案6】:

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

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

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

    为了抑制错误消息,我们使用“@”运算符,例如:

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

    【讨论】:

    • 这是一个完美的例子,说明为什么 PHP 首先有这种@ 解决方法。其他编程语言都有统一的异常处理来处理这种场景*.com/questions/1087365
    • @dreftymac 没错!
    【解决方案7】:

    @ 抑制错误消息。

    在代码sn-ps中使用如:

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

    如果域“http://www.exaple.com”不可访问,则会显示错误,但 @ 则不会显示任何内容。

    【讨论】:

      【解决方案8】:

      如果打开失败,则会产生 E_WARNING 级别的错误。您可以使用 @ 来抑制此警告。

      【讨论】:

        【解决方案9】:

        PHP 支持一种错误控制运算符:@ 符号 (@)。当附加到 PHP 中的表达式时,该表达式可能生成的任何错误消息都将被忽略。

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

        <?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) @-operator 仅适用于表达式。

        2) 一个简单的经验法则是:如果您可以获取某物的值,则可以在其前面加上 @ 运算符。例如,您可以将其添加到变量、函数和包含调用、常量等之前。您不能将其添加到函数或类定义或条件结构(例如 if 和 foreach 等)之前。

        警告:-

        目前“@”错误控制运算符前缀甚至会禁用 将终止脚本的严重错误的错误报告 执行。除其他外,这意味着如果您使用“@” 抑制某个功能的错误,或者它不可用 或者被打错了,脚本会死在那里,没有 说明原因。

        【讨论】:

          【解决方案10】:

          可能值得在此处添加一些提示,使用 @ 时您应该注意,要完整查看这篇文章:http://mstd.eu/index.php/2016/06/30/php-rapid-fire-what-is-the-symbol-used-for-in-php/

            1234563 >
          1. 在包含前面加上 @ 会将包含文件中的所有错误设置为错误级别 0

          【讨论】:

            【解决方案11】:

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

            【讨论】:

              最近更新 更多