September 12th, 2024

Why I Avoid Using Empty() in PHP? A Closer Look

The author critiques the PHP function empty() for its misleading behavior, recommending strict comparisons (===) for accurate checks to avoid confusion and bugs, especially for new developers.

Read original articleLink Icon
Why I Avoid Using Empty() in PHP? A Closer Look

The article discusses the author's reservations about using the PHP function empty(). While it appears to be a straightforward way to check if a variable is empty, its behavior is more complex than it seems. The function considers various values, including 0, "0", and false, as empty, which can lead to unexpected results in code, particularly in production environments. For instance, if a JSON response includes a distance value of "0.0", using empty() would incorrectly indicate that the distance is not set, even though it is a valid number. The author advocates for using strict comparisons (===) instead of empty() to ensure that only specific cases are evaluated, thus avoiding potential bugs. The misleading name of empty() can confuse developers, especially those new to PHP, leading to incorrect assumptions about its functionality. The article concludes by emphasizing the importance of understanding PHP functions thoroughly and opting for precise checks to enhance code reliability.

- The PHP function empty() can lead to unexpected behavior by treating values like 0 and false as empty.

- Using strict comparisons (===) is recommended for more accurate value checks.

- Misleading function names can cause confusion and bugs, especially for new developers.

- Understanding the nuances of PHP functions is crucial for writing robust code.

- Precise checks can prevent issues in production environments.

Related

The many faces of undefined in JavaScript

The many faces of undefined in JavaScript

JavaScript's handling of undefined values, including null and falsy values, can confuse developers. TypeScript introduces nuances with function arguments and void type. Recommendations suggest treating undefined as null to avoid issues.

Optimizing JavaScript for Fun and for Profit

Optimizing JavaScript for Fun and for Profit

Optimizing JavaScript code for performance involves benchmarking, avoiding unnecessary work, string comparisons, and diverse object shapes. JavaScript engines optimize based on object shapes, impacting array/object methods and indirection. Creating objects with the same shape improves optimization, cautioning against slower functional programming methods. Costs of indirection like proxy objects and function calls affect performance. Code examples and benchmarks demonstrate optimization variances.

Programmers Should Never Trust Anyone, Not Even Themselves

Programmers Should Never Trust Anyone, Not Even Themselves

Programmers are warned to stay cautious and skeptical in software development. Abstractions simplify but can fail, requiring verification and testing to mitigate risks and improve coding reliability and skills.

Don't use null objects for error handling

Don't use null objects for error handling

The article critiques using null objects for error handling in programming, arguing it misleads users and propagates errors. It advocates for immediate error handling and context-based strategies instead.

Why Not Comments

Why Not Comments

The article emphasizes the significance of "why not" comments in programming, highlighting their role in explaining decision-making and trade-offs that identifiers alone cannot convey, while questioning self-documentation limits.

Link Icon 11 comments
By @joshstrange - 5 months
This entire post is dedicated to using the wrong tool for the job…

Use isset if you want to see if the variable is set, you should never be casting client input unless it’s coming from query params (or form post I guess but at that point use JSON).

“empty” is a useful tool, provided you take into account things like “is this allowed to be 0/empty-string/etc”.

Lastly:

> After a lengthy debugging session, we realized that empty() was treating 0 as "empty", causing our validation to fail unexpectedly.

Lengthy? To notice an empty check failing? Look, the codebase I work on has its warts, all older codebases do, but unless you have no XDebug, forgot how to log to file or echo to the client, and/or aren’t capable of searching a codebase for the error you got and tracing it back from there then I can’t believe that would be a “Lengthy” process to track down. Even if you are returning a generic error to the client, surely you are logging the real error to a log somewhere?

By @ddtaylor - 5 months
Thankfully others have correctly identified this is not a real use case for empty and someone wrote an entire article about it.

The value that empty() provides in PHP is similar to a null coalescing operator in many languages:

    if (empty($foo->bar['baz'])) {
In this line of code all of the above can be missing. $foo can be an undefined variable, let alone one that has a value, and likewise all of the members, arrays, keys, etc. can also be missing. It does not throw an exception or trigger any warnings/errors to be logged, since, well, that's the purpose of empty.

If you want similar-ish behavior but you're not interested in the problems associated with the empty semantics, use isset() as it has the same properties for non-existent keys.

By @chiefalchemist - 5 months
It's not a matter of avoiding empty(). It's a matter of only using it when it's the correct tool. The examples were examples of someone using a screwdriver when they needed a hammer. That's not the screwdriver's fault.
By @chx - 5 months
You are using comparison like this after a float cast?? That's a paddlin'.
By @Cyberdog - 5 months
In PHP, as in other languages, numeric types that aren't ints should be avoided as much as possible. If you don't know why, smarter people can explain it, but the basics are that the binary nature of computers (every value is 0, 1, or a combination thereof) doesn't really work for reflecting decimal values without some level of fakery.

When working with things like money amounts, lengths, etc, store values as ints of the smallest denominator you support. For example, store $1.23 as 123 cents, or 4.567 meters as 4567 tenths of a centimeter. If you want to still allow the user to be able to, for example, enter a price as 1.23, multiply by 100 on input (like `$priceInCents = round($_POST['price'] * 100);`) and divide by 100 when displaying the value(`number_format($priceInCents / 100, 2)`), but keep it as an int all the way in between.

In terms of PHP, this also makes empty() a lot more predictable, because once a value is cast as int, the only time empty() will return true is if it is zero - or you could explicitly code `$priceInCents === 0` and have the exact same result.

By @PaulHoule - 5 months
All programming languages have some problems in this department. Some lisps for instance use the empty list nil for false, others have a distinct #f value. Each of those choices has strengths and weaknesses.

Dynamic programming languages usually have some arbitrary rules about what X is treated true or false in

  if(X) (…}
whatever rules are used are what you want almost always except for the times that they aren’t. A strongly typed language like Java will require X to be a boolean which now puts a load on the programmer to choose some f such that

   if(f(X)) {}
which could be correct every time in principle but a small increase in cognitive load is certain while most likely the f you choose (inclusive of your choice and it’s action) will do the right thing almost all the time except when it doesn’t. So I wouldn’t laugh at any particular programming language’s almost-right choice for ‘casting’ any to boolean because people are going to screw it up in any programming language.
By @cies - 5 months
There's an entire subreddit making fun of PHP quirks:

https://www.reddit.com/r/lolphp

Here the top posts of all time:

https://www.reddit.com/r/lolphp/top/?t=all

By @goshx - 5 months
In both examples, to check distance and price, the author should have simply used is_numeric()
By @Faelian2 - 5 months
Do you guys know if `!isset()` is a good alternative ? Or if it also has some shortcomings ?
By @Circlecrypto2 - 5 months
While I appreciate the availability of empty(), I appreciate this article as it clearly states why we should use stricter comparisons. Avoid mistakes, and conserve resources.