PHP has the habit of evaluating (int)0 and (string)"0" as empty when using the empty()
function. This can have unintended results if you expect numerical or string values of 0. How can I "fix" it to only return true to empty objects, arrays, strings, etc?
Improving empty()
is anything but simple.
First of all, after all those years since this question had been asked, PHP changed its approach towards much more strict typing. And therefore, using empty()
, due to its ambiguous nature, is not recommended at all.
Besides, empty()
is frowned upon for another reason: it does isset()
under the hood (being essentially a compact form for !isset($var) || !$var
) and therefore does error suppression for a possibly helpful error message, when you are trying to access a variable that doesn't exist.
Therefore, you are encouraged to write a code where all your variables are set and assigned certain type. This done, instead of using empty()
, you can always use just a comparison, according to variable's type:
$var !== 0
$var !== ''
$var !== []
// etc.
However, there is also an issue with outside variables that are not under the developer's control. In this case it is advised to validate such values first, in the meaning of checking every input value against a set of rules, and then either have all input assigned to local variables if all values are OK, or reject the request. During this process some variables can be assigned default values, if not present in the request but not being required.
But well, in case you aren't familiar with strict typing and wants just a more strict substitution, here it goes:
!isset($var) || !($var || (is_scalar($var) && strlen($var)))
Here, we are essentially recreating the empty()
's behavior, but also adding another condition: in case it's a scalar value, also check its string length and only return true
if it's zero. So it returns true
for the following values
Sometimes it could be also a good idea to throw in a trim()
call:
!isset($var) || !($var || (is_scalar($var) && strlen(trim($var))))
The code appears to be lengthy, but wrapping it in a function is not that simple either, as such a function will lose the ability to suppress the "Undefined variable" warning. To overcome it, we can define this function's parameter to be passed by reference.
function strict_empty(&$var)
{
return !($var || (is_scalar($var) && strlen(trim($var))));
}
But it has possibly unwanted side effects. For example, once we check a non-existent variable with this function, this variable will appear defined after the call.
Therefore, I strongly advise to just have all variables deliberately set and assigned certain type, and then compered to a value that is considered empty for this type, as explained above.
By the way, another approach is used in Laravel's blank()
function explained in this answer, which is quite smart, as it doesn't suppress the warning and also assumes a boolean value already meaningful (and therefore not "empty"), no matter if it's true
or false
.