A logical first step would be to fix all of those functions in PHP that end up requiring the use of @. Once that is done then we could move forward with removing all @ use.
Another one that I ran into at the same time as parse_url is that passing NULL to urldecode would throw a notice, which was simpler to @ away then check first since it always returned an empty string anyway.
PHP doesn't use threads unless you are using the pthreads extension [1]. I am not sure how it would affect that ext. Normally it won't affect any other PHP scripts that are running.
Some of the weirder OS-specific function behaviors can be a rationalized a little better if you view PHP functions not as sane, complete library functions, but rather as thin wrappers to the underlying OS. For mail() it basically just wraps the system's mail program in Linux (which comes with a huge number of dangerous gotchas for the uninitiated) and I imagine in Windows it wraps the local mail program which seems to have a gotcha with periods. I think a lot of the file management functions are the same.
That's one of the many problems with PHP's underlying design philosopy: instead of providing a higher-level interface that stays consistent across platforms, it exposes low-level OS gunk and gotchas through its thin wrappers on low-level-ish functions. I put together phpbestpractices.org a few months ago in an attempt to document some of those common gotchas and provide sane alternatives.
>PHP functions not as sane, complete library functions, but rather as thin wrappers to the underlying OS.
Except they're not really that thin.
>in Windows it wraps the local mail program which seems to have a gotcha with periods
Nope, in Windows it implements the SMTP protocol, on UNIX it runs sendmail.
>instead of providing a higher-level interface that stays consistent across platforms, it exposes low-level OS gunk and gotchas through its thin wrappers on low-level-ish functions.
Except it doesn't. There's quite a few things that are named like OS functions, but are implemented internally. For example, all the C stdlib-like string functions.
My mistake then :) I admit I haven't read the source, I'm just going off of the quirkiness of cross-platform PHP and the way the functions seem to behave.
It doesn't actually change the INI file. It changes the error_reporting setting in memory while that one function is executing and when it finishes it changes it back.
I don't see how this is a 'side effect'. It accomplishes the exact task it is designed to and doesn't do any quirky, or 'side', behavior to the script.
Also, I wouldn't be worried about one lookup. I'm pretty sure everything in PHP is in a hash map.
No, it's actually a good idea. That way I can programmatically check if any error is going to be reported inside of a method or function that's being silenced. And, on top of that, override the silencing within a method or function directly. Using an established interface provides me with a ton of options ... options I wouldn't have if it did some sort of internal voodoo.
One reason you might actually want to silence a warning.
You might be developing an application that functions in some P2P type fashion or is specifically intended to be used in situations where network access will be intermittent (on a boat perhaps?).
In such a case a mysql_connect call may have a high chance of failing and your application is designed in such a way as to assume that this is likely (i.e working with the return code).
In such a case failing the connection is not an error but expected behaviour.
Problem is when you suppress the error to handle failed connections but didn't anticipate other errors which go unnoticed and make tracking bugs VERY difficult.
This flags a design flaw, perhaps in mysql_connect. If a warning is trivial enough that it's reasonable to silence, it shouldn't exist. Otherwise, it's not reasonable to silence it!
I find it hard to believe that this is actually considered acceptable.
Surely that depends on your application, in 99.9% of cases where you are using LAMP to host some site a failed mysql_connect is probably an epic fail condition.
My point is rather that there may certainly be applications where this is not the case.
This is an area where exceptions are better than dumb warnings.
> if((!isset($x)) || (empty($x))) { echo('Custom Error'); } else { //Do the work }
You're duplicating your efforts. empty() takes into account if a variable or key has been initialized, and also if it has a non-false value. isset() only checks if the variable/key has been intialized and nothing else.
It's interesting to find out just how many ways @ is bad but this article is going to fall on deaf ears. The people that can be convinced that it's bad are already not using it. Those that need to be told why the "ignore broken things and keep on trucking" operator is bad, aren't paying attention anyways.
There are cases where you want something silenced. In my code base, there is one place where it is used and I need it there.
I frequently use file_get_contents to retrieve data stored on external servers. If there is a network error or the external service goes down temporarily, it will trigger an error. I don't want my log files flooded with transient error messages that are outside of my control. Instead, I just want it to try again. @ makes this possible.
I understand that decision, but I actively try to remove any extensions that I can do without to keep the PHP binary slim and even more reliable. My personal way of doing things, that's all. file_get_contents can do everything the curl extensions can, provided that you use the context options, so I just use that and remove curl when I compile the PHP binary.
Some negative comments about the @-operator seem to be very religious. It's just a tool that one can use for good or for evil. Many of the reasons not to use @ described are valid, but there are cases when it makes much cleaner code. E.g. instead of doing:
if (array_key_exists($key, $a) && $a[$key] == $value) dostuff();
you can do:
if (@$a[$key] == $value) dostuff();
This works really well when you don't care whether $a[$key]is present or not, and when you care only whether it contains a certain $value. In complex comparisons the code readability difference is huge!
45 comments
[ 3.4 ms ] story [ 86.7 ms ] threadhttp://php.net/manual/en/function.parse-url.php
5.3.3 Removed the E_WARNING that was emitted when URL parsing failed.
The opcode examination is particularly damning.
I would like to see what PHP 5.4 generates though, the changelog states
Aha! Found the revision: http://svn.php.net/viewvc?view=revision&revision=302442Can't make this stuff up.
I can't think of another way to do it that wouldn't effectively reduce to this anyway.
[1] https://github.com/krakjoe/pthreads
Like the fact that the language's grammar is used to do primitive type checking, meaning some combinations of accessors cause errors.
Or the fact the mail sending function doesn't work if one of the lines in the email begins with a period, but only if you're on Windows.
That's one of the many problems with PHP's underlying design philosopy: instead of providing a higher-level interface that stays consistent across platforms, it exposes low-level OS gunk and gotchas through its thin wrappers on low-level-ish functions. I put together phpbestpractices.org a few months ago in an attempt to document some of those common gotchas and provide sane alternatives.
Except they're not really that thin.
>in Windows it wraps the local mail program which seems to have a gotcha with periods
Nope, in Windows it implements the SMTP protocol, on UNIX it runs sendmail.
>instead of providing a higher-level interface that stays consistent across platforms, it exposes low-level OS gunk and gotchas through its thin wrappers on low-level-ish functions.
Except it doesn't. There's quite a few things that are named like OS functions, but are implemented internally. For example, all the C stdlib-like string functions.
Also, I wouldn't be worried about one lookup. I'm pretty sure everything in PHP is in a hash map.
You might be developing an application that functions in some P2P type fashion or is specifically intended to be used in situations where network access will be intermittent (on a boat perhaps?).
In such a case a mysql_connect call may have a high chance of failing and your application is designed in such a way as to assume that this is likely (i.e working with the return code). In such a case failing the connection is not an error but expected behaviour.
I find it hard to believe that this is actually considered acceptable.
My point is rather that there may certainly be applications where this is not the case.
This is an area where exceptions are better than dumb warnings.
http://semi-rad.com/2013/01/everything-is-epic/
Maybe the solution is to use php 5.4 if it makes better silence code but I am having a hard time letting go of suhosin.
$x = @$f["x"] is right place to use it.
$x = @custom_func() - is a disaster, do not do it
No, it's not. There's built-in methods for that: isset() and empty().
if(function_exists(custom_func) { $x = @custom_func(); }
if((!isset($x)) || (empty($x))) { echo('Custom Error'); } else { //Do the work }
This may be considered verbose, but can be useful if custom or "sometimes" installed libraries are involved
http://php.net/manual/en/function.call-user-func.php
Why would you prepend @ to your function call?
> if((!isset($x)) || (empty($x))) { echo('Custom Error'); } else { //Do the work }
You're duplicating your efforts. empty() takes into account if a variable or key has been initialized, and also if it has a non-false value. isset() only checks if the variable/key has been intialized and nothing else.
I frequently use file_get_contents to retrieve data stored on external servers. If there is a network error or the external service goes down temporarily, it will trigger an error. I don't want my log files flooded with transient error messages that are outside of my control. Instead, I just want it to try again. @ makes this possible.