What is the use of the @ symbol in PHP?
Asked Answered
C

11

638

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

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

What is the use of this symbol?

Choppy answered 23/6, 2009 at 12:8 Comment(2)
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 AidenChoppy
Suppressing errors (although nice) could cause errors down the road when maintaining the codebase... https://mcmap.net/q/65142/-is-it-alright-to-suppress-hide-php-noticesFadeout
B
254

The @ symbol is the error control operator (aka the "silence" or "shut-up" operator). It makes PHP suppress any diagnostic error messages generated by the expression associated with it. Like unary operators, it has a precedence and associativity. Below are some examples:

@echo 1 / 0;
// displays "Parse error: syntax error, unexpected T_ECHO"
// this is because "echo" is not an expression
// the script terminates because of parse error

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

@$i / 0;
// suppressed "Notice: Undefined variable: i"
// displays "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";
// displays "Fatal error: Call to undefined function foobar()"
// fatal errors are displayed even with the shut-up operator
// the script terminates because of fatal error
Begot answered 25/1, 2013 at 10:53 Comment(4)
echo @(1 / 0); is giving me DivisionByZeroError I am using php 8. Maybe becuase DivisionByZeroError was added in PHP 7?Ragtime
@Ragtime no this error was present in PHP5 when this answer was written. The behavuor of stfu operator might have changed in PHP8.Begot
But docs 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.Ragtime
@Ragtime 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.Begot
M
697

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

Morocco answered 23/6, 2009 at 12:9 Comment(2)
Cool feature.. It makes the use of isset()'s unnecessary in order to avoid undefined offset errors.Anacreontic
Wow that's a great tip! I've been checking isset for 12 long years. Imagine all the time I will save now.Cave
M
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 @...

Mu answered 23/6, 2009 at 12:9 Comment(0)
B
254

The @ symbol is the error control operator (aka the "silence" or "shut-up" operator). It makes PHP suppress any diagnostic error messages generated by the expression associated with it. Like unary operators, it has a precedence and associativity. Below are some examples:

@echo 1 / 0;
// displays "Parse error: syntax error, unexpected T_ECHO"
// this is because "echo" is not an expression
// the script terminates because of parse error

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

@$i / 0;
// suppressed "Notice: Undefined variable: i"
// displays "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";
// displays "Fatal error: Call to undefined function foobar()"
// fatal errors are displayed even with the shut-up operator
// the script terminates because of fatal error
Begot answered 25/1, 2013 at 10:53 Comment(4)
echo @(1 / 0); is giving me DivisionByZeroError I am using php 8. Maybe becuase DivisionByZeroError was added in PHP 7?Ragtime
@Ragtime no this error was present in PHP5 when this answer was written. The behavuor of stfu operator might have changed in PHP8.Begot
But docs 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.Ragtime
@Ragtime 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.Begot
N
59

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

Navelwort answered 11/1, 2010 at 14:48 Comment(0)
B
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.

Brazilin answered 27/4, 2016 at 14:35 Comment(11)
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" )Ecclesiastes
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.Outface
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(); ?Mesolithic
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.Stogy
@Stogy 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.Brazilin
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.Stogy
Ehm.... first reason is "being debuggable". – I see that as @Brazilin : 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.Gilding
The point, as mentioned in the @ docs' comments, 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)Gilding
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.Hallah
@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 @.Gilding
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.Gilding
F
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.

Frankpledge answered 14/10, 2015 at 13:2 Comment(0)
D
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);
Dalhousie answered 22/3, 2015 at 5:35 Comment(1)
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 stackoverflow.com/questions/1087365Vandiver
D
5

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

Dissociate answered 12/8, 2013 at 10:41 Comment(0)
R
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.

Ruthannruthanne answered 17/2, 2016 at 8:50 Comment(0)
N
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

Nucleoprotein answered 30/6, 2016 at 14:35 Comment(0)
K
0

@ suppresses the error message thrown by the function. fopen throws an error when the file doesn't exist. The @ symbol makes the execution point to move to the next line even if the file doesn't exist. My suggestion would be no to use this in your local environment when you develop a PHP code.

Kalpak answered 10/8, 2018 at 9:21 Comment(1)
This answer is factually incorrect. The @ symbol DOESN'T make the execution point to move to the next line even if the file doesn't exist. Because it will be moved regardless. Therefore The @ symbol simply shouldn't be used in ANY environment.Petaliferous

© 2022 - 2024 — McMap. All rights reserved.