views:

4728

answers:

18

In your opinion, is it ever valid to use the @ operator to suppress an error/warning in PHP whereas you may be handling the error?

If so, in what circumstances would you use this?

Code examples are welcome.

Edit: Note to repliers. I'm not looking to turn error reporting off, but, for example, common practice is to use

@fopen($file);

and then check afterwards... but you can get rid of the @ by doing

if (file_exists($file))
{
    fopen($file);
}
else
{
    die('File not found');
}

or similar.

I guess the question is - is there anywhere that @ HAS to be used to supress an error, that CANNOT be handled in any other manner?

+4  A: 

Yes suppression makes sense.

For example, the fopen() command returns FALSE if the file cannot be opened. That's fine, but it also produces a PHP warning message. Often you don't want the warning -- you'll check for FALSE yourself.

In fact the PHP manual specifically suggests using @ in this case!

Jason Cohen
but, surely, this can be avoided by checking file_exists($file) first?
Mez
No it can't, there are other failure conditions such as "no permissions to read" or "file busy."
Jason Cohen
+6  A: 

You can suppress database connections and handle failures yourself.

$db = @myssql_connect($host, $user, $pass);
if ($db) {
    /* proceed */
} else {
    /* display your own error */
}
@mysql_close($db);

Also, in regard to myssql_close, there's no need to alert that a connection can't be closed when it never opened.


RE: Comment

True, you could:

$db = @myssql_connect($host, $user, $pass);
if ($db) {
    /* proceed */
    mysql_close($db);
} else {
    /* display your own error */
}

But, it depends on your preference for scope alignment. I, generally, prefer to keep everything related in the same scope, on the same tabbing. So, having mysql_close within the if/else would drive me nuts. ;)

Jonathan Lonowski
Wouldn't it make more sense then to close your connection inside your IF block?
Zerofiz
Ok, so this is the one thing that @ is more than likely needed for. There's no need before hand to check whether the server is connectable, and it throws a warning.
Mez
"myssql_connect" is actually "mysql_connect"
alexy13
+2  A: 

is there not a way to suppress from the php.ini warnings and errors? in that case you can debug only changing a flag and not trying to discovering which @ is hiding the problem.

Enreeco
Mez
A: 

You do not want to suppress everything, since it slows down your script.

And yes there is a way both in php.ini and within your script to remove errors (but only do this when you are in a live environment and log your errors from php)

<?php
    error_reporting(0);
?>

And you can read this for the php.ini version of turning it off.

Ólafur Waage
I'm not looking for a way to turn it off, I'm looking for whether there's a reason to use it, as in anything that cannot be handled without using @ (one item so far - mysql_connect)
Mez
Hi! What makes it slow down the script? thanks!
Industrial
@Industrial it is doing extra work suppressing the errors. Since it is supposed to display an error but finds an @ there and has do deal with it dynamically.
Ólafur Waage
Ah! So it would then be better to follow your example - error_reporting(0);?
Industrial
@Industrial If you're logging errors to somewhere else yes.
Ólafur Waage
+3  A: 

Error suppression should be avoided unless you know you can handle all the conditions.

This may be much harder than it looks at first.

What you really should do is rely on php's "error_log" to be your reporting method, as you cannot rely on users viewing pages to report errors. ( And you should also disable php from displaying these errors )

Then at least you'll have a comprehensive report of all things going wrong in the system.

If you really must handle the errors, you can create a custom error handler

http://php.net/set-error-handler

Then you could possibly send exceptions ( which can be handled ) and do anything needed to report weird errors to administration.

Kent Fredric
I know I shouldn't supress the errors, but some things will throw an E_WARNING or an E_NOTICE, when it's not needed to actually show that to the end user, and in a lot of cases, it can be avoided to actually theow these. except, for now in the case of mysql_open
Mez
@martin meredith: thats why you use "error_log" and "display_errors=false"
Kent Fredric
@Kent - Best answer on this page by far! [edit: make that second best, because I just added one :P] @Mez - As Kent has suggested, set up an error handler that only displays errors to you.
Gerry
A: 

I use it when trying to load an HTML file for processing as a DOMDocument object. If there are any problems in the HTML... and what website doesn't have at least one... DOMDocument->loadHTMLFile() will throw an error if you don't suppress it with @. This is the only way (perhaps there are better ones) I've ever been successful in creating HTML scrapers in PHP.

Steve Paulo
+2  A: 

Using @ is sometimes counter productive. In my experience, you should always turn error reporting off in the php.ini or call

error_reporting(0);

on a production site. This way when you are in development you can just comment out the line and keep errors visible for debugging.

Eric Lamb
I prefer for errors to be visible. What I'm trying to work out, if is there is any way that you would have to use an @ or you might have an error, that cannot be caught before.
Mez
I've never seen an instance where using @ for error suppression was a positive thing. It hides all future errors, not just the one that you wanted to ignore.
Gerry
A: 

One place I use it is in socket code, for example, if you have a timeout set you'll get a warning on this if you don't include @, even though it's valid to not get a packet.

$data_len = @socket_recvfrom( $sock, $buffer, 512, 0, $remote_host, $remote_port )
Don Neufeld
+3  A: 

If you don't want a warning thrown when using functions like fopen(), you can suppress the error but use exceptions:

try {
    if (($fp = @fopen($filename, "r")) == false) {
        throw new Exception;
    } else {
        do_file_stuff();
    }
} catch (Exception $e) {
    handle_exception();
}
dirtside
This is my preferred method
mabwi
+5  A: 

I would suppress the error and handle it. Otherwise you may have a TOCTOU issue (Time-of-check, time-of-use. For example a file may get deleted after file_exists returns true, but before fopen).

But I wouldn't just suppress errors to make them go away. These better be visible.

phjr
The problem with that is that you end up suppressing other errors that you didn't predict and then spend your entire day trying to track down a bug that isn't throwing any errors.In the rare situation of a TOCTOU issue I think it's far better for an error to be thrown as PHP errors should not be displayed to end users anyway, but it will still allow somebody to be aware of the situation through logging of errors or displaying it if the script is running in a development environment. Error supression is the best way to hide a problem. (eg. files being deleted :) )
Gerry
This is fine, but for the love of not being hunted down and murdered, please check for the right error. I once spent way too long tracking down a database problem - I was seeing Close() failures, and nothing was working. Eventually I discovered that the genious @'d the initial connection, and the "else" check was essentially empty. Removing the @, I was immediately able to discern that the connection credentials were bad.
anonymous coward
A: 

I think php's errors and warnings are annoying as hell so I usually come up with constructs like this (which i wrote just a couple of hours ago):

public function Load( $path, $options )
{
    if( @parent::Load( $path, $options ) )
    {
        $this->XInclude();
        $this->ResetXPath();
        $this->ResetHtml();
        $this->ApplyControls();
    }
    else
    {
        throw new WebPageTemplateLoadException( 'The template is not well-formed.' );
    }
}

Which is in my WebPage class that extends DOMDocument. Exceptions are a cleaner way to deal with errors imho, be it fatal or non fatal. And if you leave away the @ suppression, your logs or worse, the user visible output of the scripts will show it.

I will admit that extending DOMDocument is a kind of special-case situation (because its implementation is in c and it is more than just a bit foreign to php, but yeah, using @ to suppress is completely valid.

Kris
+24  A: 

=================================================
Note: Firstly, I realise 99% of PHP developers use the error suppression operator (I used to be one of them), so I'm expecting any PHP dev who sees this to down vote me, but please bookmark this so that you can come back and change it to an up vote in a couple of years when you realise I was right. =================================================

In your opinion, is it ever valid to use the @ operator to suppress an error/warning in PHP whereas you may be handling the error?

Short answer:
NO!!!!!!!!!!!!!!!!!!!!

Longer more correct answer:
I don't know as I don't know everything, but so far I haven't come across a situation where it was a good solution.

Why it's bad:
In what I think is about 7 years using PHP now I've seen endless debugging agony caused by the error suppression operator and have never come across a situation where it was unavoidable.

The problem is that the piece of code you are suppressing errors for, may currently only cause the error you are seeing; however when you change the code which the suppressed line relies on, or the environment in which it runs, then there is every chance that the line will attempt to output a completely different error from the one you were trying to ignore. Then how do you track down an error that isn't outputting? Welcome to debugging hell!

It took me many years to realise how much time I was wasting every couple of months because of suppressed errors. Most often (but not exclusively) this was after installing a third party script/app/library which was error free in the developers environment, but not mine because of a php or server configuration difference or missing dependency which would have normally output an error immediately alerting to what the issue was, but not when the dev adds the magic @.

The alternatives (depending on situation and desired result):
Handle the actual error that you are aware of, so that if a piece of code is going to cause a certain error then it isn't run in that particular situation. But I think you get this part and you were just worried about end users seeing errors, which is what I will now address.

For regular errors you can set up an error handler so that they are output in the way you wish when it's you viewing the page, but hidden from end users and logged so that you know what errors your users are triggering.

For fatal errors set display_errors to off (your error handler still gets triggered) in your php ini and enable error logging. If you have a development server as well as a live server (which I recommend) then this step isn't necessary on your development server, so you can still debug these fatal errors without having to resort to looking at the error log file. There's even a trick using the shutdown function to send a great deal of fatal errors to your error handler.

In summary:
Please avoid it. There may be a good reason for it, but I'm yet to see one, so until that day it's my opinion that the (@) Error suppression operator is evil.

You can read my comment on the Error Control Operators page in the PHP manual if you want more info.

Edit: Btw to the 2 down voters (3 up, which is surprising) so far, it would be great if you left a comment. If I'm wrong on this then I'd love to hear why. On the other hand, if you are just down voting me because I'm arrogant, then fair enough. That's a fair call, but please state it as your reason.

Gerry
This is absolutely correct. Suppressing errors is a fundamental mistake. Use your error handler, or use exceptions, don't hide the error.
mabwi
+3  A: 

I NEVER allow myself to use '@'... period.

When I discover usage of '@' in code, I add comments to make it glaringly apparent, both at the point of usage, and in the docblock around the function where it is used. I too have been bitten by "chasing a ghost" debugging due to this kind of error suppression, and I hope to make it easier on the next person by highlighting its usage when I find it.

In cases where I'm wanting my own code to throw an Exception if a native PHP function encounters an error, and '@' seems to be the easy way to go, I instead choose to do something else that gets the same result but is (again) glaringly apparent in the code:

$orig = error_reporting(); // capture original error level
error_reporting(0);        // suppress all errors
$result = native_func();   // native_func() is expected to return FALSE when it errors
error_reporting($orig);    // restore error reporting to its original level
if (false === $result) { throw new Exception('native_func() failed'); }

That's a lot more code that just writing:

$result = @native_func();

but I prefer to make my suppression need VERY OBVIOUS, for the sake of the poor debugging soul that follows me.

ashnazg
A: 

The only place where I really needed to use it is the eval function. The problem with eval is that, when string cannot be parsed due to syntax error, eval does not return false, but rather throws an error, just like having a parse error in the regular script. In order to check whether the script stored in the string is parseable you can use something like:

$script_ok = @eval('return true; '.$script);

AFAIK, this is the most elegant way to do this.

Milan Babuškov
A: 

I've used this when I have a form with a field on it that I don't neccesarily want to collect. It is a lot faster than checking whether a POST variable exists, and then using it somehow.

dunxd
A: 

If you are using a custom error handling function and wanna suppress an error (probably a known error), use this method. The use of '@' is not a good idea in this context as it will not suppress error if error handler is set.

Write 3 functions and call like this.

# supress error for this statement
supress_error_start();  
$mail_sent = mail($EmailTo, $Subject, $message,$headers);
supress_error_end(); #Don't forgot to call this to restore error.  

function supress_error_start(){
    set_error_handler('nothing');
    error_reporting(0);
}

function supress_error_end(){
    set_error_handler('my_err_handler');
    error_reporting('Set this to a value of your choice');
}

function nothing(){ #Empty function
}

function my_err_handler('arguments will come here'){
      //Your own error handling routines will come here
}
Sumesh
A: 

I use @ in my class auto loading code. The problem is that PHP doesen't supply a file_exists_in_include_path method, or similar, so apart from exploding the include path, it's far easier to use @include. If the include fails, the user still gets a class not found exception, and if I was doing a manual check for the file existing I would throw the same exception anyway (the error is not that the file does not exist, but that the class cannot be found), so here I think is a valid reason to use @, it saved time and code, an error will still be thrown if there is a problem and, most importantly, it works.

Sprog
A: 

Most people do not understand the meaning of error message.
No kidding. Most of them.

They think that error messages are all the same, says "Something goes wrong!"
They don't bother to read it.
While it's most important part of error message - not just the fact it has been raised, but it's meaning. It can tell you what is going wrong. Error messages are for help, not for bothering you with "how to hide it?" problem. That's one of the biggest misunderstandings in the newbie web-programming world.

Thus, instead of gagging error message, one should read what it says. It has not only one "file not found" value. There can be thousands different errors: permission denied, save mode restriction, open_basedir restriction etc.etc. Each one require appropriate action. But if you gag it you'll never know what happened!

The OP is messing up error reporting with error handling, while it's very big difference!
Error handling is for user. "something happened" is enough here.
While error reporting is for programmer, who desperately need to know what certainly happened.

Thus, never gag errors messages. Both log it for the programmer, and handle it for the user.

Col. Shrapnel