633

I have seen uses of @ in front of certain functions, like the following:

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

What is the use of this symbol?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
sv_in
  • 13,929
  • 9
  • 34
  • 55
  • 3
    Both RichieHindle and Aiden Bell gave the right answer but since I can only set one answer as accepted, I will choose the first one. Sorry Aiden – sv_in Sep 30 '09 at 05:02
  • 1
    Suppressing errors (although nice) could cause errors down the road when maintaining the codebase... http://stackoverflow.com/a/7116175/282343 – dennismonsewicz Mar 22 '12 at 19:41

11 Answers11

694

It suppresses error messages — see Error Control Operators in the PHP manual.

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
RichieHindle
  • 272,464
  • 47
  • 358
  • 399
  • 1
    Cool feature.. It makes the use of `isset()`'s unnecessary in order to avoid `undefined offset` errors. – W.M. Dec 17 '16 at 20:55
495

It suppresses errors.

See Error Control Operators in the manual:

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 @...

gnat
  • 6,213
  • 108
  • 53
  • 73
Aiden Bell
  • 28,212
  • 4
  • 75
  • 119
251

The @ symbol is the error control operator (aka the "silence" or "shut-up" operator). It makes PHP suppress any error messages (notice, warning, fatal, etc) generated by the associated expression. It works just like a unary operator, for example, it has a precedence and associativity. Below are some examples:

@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"

What exactly happens if you use a custom error handler instead of the standard PHP error handler:

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 @.

This is illustrated in the following code example:

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"

The error handler did not check if @ symbol was in effect. The manual suggests the following:

function better_error_handler($errno, $errstr, $errfile, $errline, $errcontext) {
    if(error_reporting() !== 0) {
        echo "[better_error_handler]: $errstr";
    }
    // take appropriate action
    return true;
}
Salman A
  • 262,204
  • 82
  • 430
  • 521
  • `echo @(1 / 0);` is giving me `DivisionByZeroError` I am using php 8. Maybe becuase `DivisionByZeroError` was added in PHP 7? – Omkar76 Jun 18 '21 at 13:34
  • @Omkar76 no this error was present in PHP5 when this answer was written. The behavuor of stfu operator might have changed in PHP8. – Salman A Jun 18 '21 at 13:49
  • But [docs](https://www.php.net/manual/en/class.divisionbyzeroerror.php) say it's added in 7. I think it used to be a warning only. Now it's throwing exception. Which @ is apparently unable to suppress. – Omkar76 Jun 18 '21 at 14:05
  • @Omkar76 the comments on that page seems to indicate that it is no longer a warning but an exception... something that is beyond the score of `@` operator. – Salman A Jun 18 '21 at 18:23
59

Also note that despite errors being hidden, any custom error handler (set with set_error_handler) will still be executed!

nickf
  • 537,072
  • 198
  • 649
  • 721
46

Like already some answered before: The @ operator suppresses all errors in PHP, including notices, warnings and even critical errors.

BUT: Please, really do not use the @ operator at all.

Why?

Well, because when you use the @ operator for error supression, you have no clue at all where to start when an error occurs. I already had some "fun" with legacy code where some developers used the @ operator quite often. Especially in cases like file operations, network calls, etc. Those are all cases where lots of developers recommend the usage of the @ operator as this sometimes is out of scope when an error occurs here (for example a 3rdparty API could be unreachable, etc.).

But what's the point to still not use it? Let's have a look from two perspectives:

As a developer: When @ is used, I have absolutely no idea where to start. If there are hundreds or even thousands of function calls with @ the error could be like everyhwere. No reasonable debugging possible in this case. And even if it is just a 3rdparty error - then it's just fine and you're done fast. ;-) Moreover, it's better to add enough details to the error log, so developers are able to decide easily if a log entry is something that must be checked further or if it's just a 3rdparty failure that is out of the developer's scope.

As a user: Users don't care at all what the reason for an error is or not. Software is there for them to work, to finish a specific task, etc. They don't care if it's the developer's fault or a 3rdparty problem. Especially for the users, I strongly recommend to log all errors, even if they're out of scope. Maybe you'll notice that a specific API is offline frequently. What can you do? You can talk to your API partner and if they're not able to keep it stable, you should probably look for another partner.

In short: You should know that there exists something like @ (knowledge is always good), but just do not use it. Many developers (especially those debugging code from others) will be very thankful.

Andreas
  • 2,821
  • 25
  • 30
  • 1
    Some warnings can only be reliably suppressed using @ (eg fopen(), where any attempt to predict the result is subject to a race condition), if you have code to handle the error condition in a tidier way then usuig `@` is the right thing do do, this is especially useful especially if you aren't returning `text/html` (or similar) to the client. (maybe returning `image/png` or "json" ) – Jasen Feb 16 '17 at 01:04
  • 2
    You should not be suppressing warnings - they are stating you have done something wrong. There is no race condition in which you can not properly check or handle state. – Ryan Rentfro Feb 23 '17 at 19:47
  • 1
    I have the following in my code in a few places. `if( session_status() == PHP_SESSION_NONE ) session_start();` It's a legacy app I inherited, and there are places where the setup script gets called multiple times, so I have to test. What, if any, problem would there be in simply using `@session_start();` ? – Stephen R Jul 16 '18 at 18:12
  • If you know what you're doing and use it sparingly/strategically, it is worth using. `@$this->stats['device_os'][$date][$creative_id][$device_id][$operating_system]['clicks']++;` is a lot better than the alternative of having isset checks at each level and filling it in when it's not. – dtbarne Sep 20 '18 at 21:45
  • 1
    @dtbarne No, it's not. :-/ I heavily disagree. Of course you have to check if the parent itself exists, before you exist a subelement of an array... It's just plain dirty what you are doing and far away from being a best-practice. – Andreas Sep 21 '18 at 08:46
  • 1
    Give me a good reason why adding 12+ lines of code and adding no value but only reducing readability and brevity of the code is worth doing other than that you read somewhere some time that it's "plain dirty" and maybe you can change my mind. – dtbarne Feb 18 '19 at 23:49
  • Ehm.... first reason is "being debuggable". – I see that as @Andreas : no way that choosing `@`-operator would be a "better choice"; it's always just a "convenient choice" (hence: high risk for technical debt). Especially since we have a `??`-Null-Coalescing-Operator, if one is lazy to use `isset()`, that would keep that single line, well, single. – Kamafeather Dec 02 '20 at 14:05
  • 1
    The point, as mentioned in the [`@` docs' comments](https://www.php.net/manual/en/language.operators.errorcontrol.php#90987), is that you can't predict everything that will happen, so you blindly risk to suppress errors that you didn't think about. Even in simple cases `@` can be evil, make you clueless, unable to debug. And it's not even so much more readable (similarly to the `!`-operator); being more explicit would make the code more readable & understandable to *any kind of developer* that needs to deal with your code (I still remember, first time I saw it, how puzzling `@` was to me) – Kamafeather Dec 02 '20 at 14:10
  • 1
    I don't know how this has so many upvotes. You can use it on an array to make it return null instead of throwing a error/warning. @$arr['index'] is much better than isset( $arr['index'] ) ? $arr['index'] : null. Everything you talked about in your post does not apply in this situation. Obviously, you don't use @ on random functions in your own code or on includes. It's also useful for file_get_contents(), mkdir(), etc. You should never say never IMO. Instead, weigh the costs and benefits in different situations. – Joel M Apr 26 '22 at 16:15
  • @JoelM that's a reiteration of what was already discussed. Your suggestions fails in e.g. cases where the variable type isn't array; how would you realize the mistake when using `@`? Being hermetic is cool, but tricky; especially when there are still-short & clearer alternatives to `@`. – Kamafeather Jul 05 '22 at 12:05
  • 1
    I also would consider that disk operations like `file_get_contents` or `mkdir` are among the biggest platform-dependent side effects that a PHP function can have. It's code you can't control nor debug directly, when it doesn't work. Devs reading/debugging your code will want more informative and explicit errors. Anecdote: I've personally hated when a complex Symfony component that was dealing with class bootstrapping was silently failing on file operations because of using `@`, in combination with some weird filesystem permissions set at Docker level. Trust me, it sucks to have no clue. – Kamafeather Jul 05 '22 at 12:08
8

@ suppresses error messages.

It is used in code snippets like:

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

If domain "http://www.exaple.com" is not accessible, an error will be shown, but with @ nothing is shown.

Andrey
  • 44
  • 1
  • 11
fico7489
  • 7,931
  • 7
  • 55
  • 89
7

Suppose we haven't used the "@" operator then our code would look like this:

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

And what if the file we are trying to open is not found? It will show an error message.

To suppress the error message we are using the "@" operator like:

$fileHandle = @fopen($fileName, $writeAttributes);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Sujeet Kumar
  • 1,280
  • 1
  • 17
  • 25
  • This is a perfect example for why PHP has this kind of `@` workaround in the first place. Other programming languages have uniform **exception handling** to deal with this kind of scenario https://stackoverflow.com/questions/1087365 – dreftymac Aug 21 '18 at 23:38
5

If the open fails, an error of level E_WARNING is generated. You may use @ to suppress this warning.

Kishor Singh
  • 61
  • 1
  • 1
1

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
/* 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.

?>

Note:-

1) The @-operator works only on expressions.

2) A simple rule of thumb is: if you can take the value of something, you can prepend the @ operator to it. For instance, you can prepend it to variables, function and include calls, constants, and so forth. You cannot prepend it to function or class definitions, or conditional structures such as if and foreach, and so forth.

Warning:-

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.

Ravi Hirani
  • 6,511
  • 1
  • 27
  • 42
1

It might be worth adding here there are a few pointers when using the @ you should be aware of, for a complete run down view this post: http://mstd.eu/index.php/2016/06/30/php-rapid-fire-what-is-the-symbol-used-for-in-php/

  1. The error handler is still fired even with the @ symbol prepended, it just means a error level of 0 is set, this will have to be handled appropriately in a custom error handler.

  2. Prepending a include with @ will set all errors in the include file to an error level of 0

twigg
  • 3,753
  • 13
  • 54
  • 96
1

@ suppresses the error message thrown by the function. fopen throws an error when the file doesn't exit. @ symbol makes the execution to move to the next line even the file doesn't exists. My suggestion would be not using this in your local environment when you develop a PHP code.

Barry
  • 3,303
  • 7
  • 23
  • 42