9

Is it OK to use @ when extracting a possibly missing value from a PHP array? Example:

$value = @$array['possibly_missing_key'];

The intended behavior:

if (isset($array['possibly_missing_key'])) {
    $value = $array['possibly_missing_key'];
} else {
    $value = null;
}

I want to know, before spreading the usage pattern.

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
Ivo Danihelka
  • 3,382
  • 3
  • 31
  • 27
  • 5
    Am I the only one using [array_key_exists](http://ca.php.net/manual/en/function.array-key-exists.php) instead of isset for this kind of stuff? – AlexV Dec 14 '10 at 16:40
  • 1
    *(sidenote)* `isset` does not detect a *probably missing key*. Use `array_key_exists` for that. Try `$arr = array('notMissing' => NULL);` with `isset` – Gordon Dec 14 '10 at 16:42
  • 1
    @AlexV @Gordon: I don't think it matters since the default value is NULL anyway :P – BoltClock Dec 14 '10 at 16:42
  • @AlexV - Possibly, Micro-optimization, I know, but I find isset() to be faster than array_key_exists()... probably because it's a language construct rather than a function (with all the relevant function call overhead) – Mark Baker Dec 14 '10 at 16:45
  • 4
    I'm with @AlexV on this one. There is a semantic difference between a missing key and an existing key with a value of `NULL` – Gordon Dec 14 '10 at 16:46
  • I considered using array_key_exists() in the example. That would result in comments that isset() is shorter to get the same behavior. – Ivo Danihelka Dec 14 '10 at 17:01
  • @Ivo Danihelka: You are right. Just goes to show that people will micro-optimize anything and everything to get 3 ns boost on a script which runs for 500 ms once a week, and behavior that is *almost* the same, except when it's not. *Sigh*. – Piskvor left the building Dec 14 '10 at 17:08

6 Answers6

8

The @ operator suppresses error messages, and using it potentially sets up your code for other errors and unexpected behavior that end up hard to track down. Thus it's most certainly an antipattern.

Thus, I would very much prefer the second bit. It makes it much clearer

  • that it may not be present in the array, and
  • what the default value is if it's not present

To make it more concise you can use the ternary conditional operator ?:, as seen in Mark Baker's answer. Slightly less code and more symbols but the meaning is well-recognized.

Community
  • 1
  • 1
BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
7

Actually the isset variation is the anti-pattern. If you just use isset($var)?$var:NULL with the intention to suppress the "error", then you've achieved nothing over using the proper syntax for suppressing errors. It has the same outcome, yet is less readable.

People are arguing for that because of perceived "cleanliness" and because using isset is a micro optimization. Avoiding @ and using isset as syntactic salt replacement is just cargo cult programming.

mario
  • 144,265
  • 20
  • 237
  • 291
  • Thanks for mentioning a contrarian view. – Ivo Danihelka Dec 14 '10 at 16:50
  • @IvoDanihelka: Actually I want to retreat, and add a big **it all depends**. There is not a single pattern which matches all use cases. Be flexible not religious about isset/@, use the best tool for the job at hand. – mario Dec 14 '10 at 16:53
4

Or

$value = (isset($array['possibly_missing_key'])) ? $array['possibly_missing_key']: null;
Mark Baker
  • 209,507
  • 32
  • 346
  • 385
  • 1
    +1 If using PHP >= 5.3 you can use the new shorter form: `isset($array['possibly_missing_key']) ?: null;` – webbiedave Dec 14 '10 at 16:38
  • 4
    @webbiedave: No, that would return the result of `isset(...)` and not the actual array value. – BoltClock Dec 14 '10 at 16:39
  • @webbiedave: will that short version work in this case? Will it not return the value of the `isset()` (ie true or false) rather than the variable itself? – Spudley Dec 14 '10 at 16:40
  • Suddenly I'm hankering for the null-coalescing operator (`someVar ?? someDefaultValue`) found in C#... – BoltClock Dec 14 '10 at 16:41
  • oh snap! Well, I'll leave the comment so he can see the shorter form for future use. – webbiedave Dec 14 '10 at 16:41
1

Ignoring warnings is definitely an antipattern; so yes, it's an anti-pattern (and I can guarantee that if you learn to suppress warnings, one of them will come back and bite you in the posterior, if not worse).

Also, while the second version is more verbose, it gives the uninitialized variable a known state (or can be used to handle the problem, if the variable is supposed to be filled).

Piskvor left the building
  • 91,498
  • 46
  • 177
  • 222
1

The third option:

$value = (isset($array['key']) ? $array['key'] : null);

I know this doesn't directly answer the question; I would have put it as a comment, except it really needed to be formatted.

The idea here is that if you're trying to make your code shorter by using a one-liner instead of an if-else block, then you can still get it into a succinct one-liner using a ternary operator, giving you the best of both worlds.

Spudley
  • 166,037
  • 39
  • 233
  • 307
  • That's not really a third option, that's a different formatting of option 2 (as it's functionally identical). Would you say that `if (x) { something }` and `if (!x) {} else { something }` are two different solutions, because they are not written the same way? – Piskvor left the building Dec 14 '10 at 16:39
  • @Piskvor - hm, that's a bit picky. It's different syntax, so I would say that yes it is a third option, even if it is effectively identical to his original code. But my point was to provide a one-liner way to do it without using `@`, since that seemed to be where his question was angling. – Spudley Dec 14 '10 at 16:46
  • Well, I'm sort of on the fence about this. The syntax is different, yet it does the same thing. You are right that it's less verbose, while keeping the functionality. (I guess it says more about my nitpicking urges than about the question at hand ;)) – Piskvor left the building Dec 14 '10 at 16:50
1

The second block of code (or Mark Baker's alternative which will work exactly the same) is better. I'm not entirely sure about PHP, but in many other programming languages, to simply ignore a variable would almost definitely throw an error. At least with the second block you are initializing the variable to some value or memory location.

Error suppression should be more commonly used if you expect a function to throw an expected error in the end-product (however, much of the time this will not be the case).

Good luck!
Dennis M.

RageD
  • 6,693
  • 4
  • 30
  • 37