Is @$array['possibly_missing_key'] an anti-pattern?
Asked Answered
D

6

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.

Doggett answered 14/12, 2010 at 16:31 Comment(7)
Am I the only one using array_key_exists instead of isset for this kind of stuff?Juna
(sidenote) isset does not detect a probably missing key. Use array_key_exists for that. Try $arr = array('notMissing' => NULL); with issetConker
@Juna @Gordon: I don't think it matters since the default value is NULL anyway :PFootslog
@Juna - 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)Springhead
I'm with @Juna on this one. There is a semantic difference between a missing key and an existing key with a value of NULLConker
I considered using array_key_exists() in the example. That would result in comments that isset() is shorter to get the same behavior.Doggett
@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.Scrubber
F
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.

Footslog answered 14/12, 2010 at 16:34 Comment(1)
I understand. The safe @ usage could mislead other developers into using it on wrong places.Doggett
O
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.

Odaodab answered 14/12, 2010 at 16:43 Comment(2)
Thanks for mentioning a contrarian view.Doggett
@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.Odaodab
S
4

Or

$value = (isset($array['possibly_missing_key'])) ? $array['possibly_missing_key']: null;
Springhead answered 14/12, 2010 at 16:35 Comment(5)
+1 If using PHP >= 5.3 you can use the new shorter form: isset($array['possibly_missing_key']) ?: null;Cubital
@webbiedave: No, that would return the result of isset(...) and not the actual array value.Footslog
@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?Slinkman
Suddenly I'm hankering for the null-coalescing operator (someVar ?? someDefaultValue) found in C#...Footslog
oh snap! Well, I'll leave the comment so he can see the shorter form for future use.Cubital
S
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).

Scrubber answered 14/12, 2010 at 16:37 Comment(0)
S
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.

Slinkman answered 14/12, 2010 at 16:38 Comment(3)
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?Scrubber
@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.Slinkman
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 ;))Scrubber
V
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.

Vish answered 14/12, 2010 at 16:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.