I realized that I am very strict about the use of PHPs empty function in code review. There isn't really any reason to use it in my opinion:
- it tests both for the existance and the non-falsy value and as a reader the writers intent is not clear.
- it does not communicate what type a variable has, seeing
empty($value)
does not narrow down what value is enough. - it hides errors caused by typos in the variable name passed to empty.
This is a list of alternatives that I recommend to use instead of empty.
// Replace
if (empty($string)) {
}
// With
if (strlen($string) === 0) {
}
Using strlen communicates that the variable is a string.
// Replace
if (empty($array)) {
}
// With
if (count($array) === 0) {
}
Using count communicates that the variable is an array.
// Replace
if (empty($array[$key])) {
}
// With
if (array_key_exists($array, $key)) {
}
// or if you know that existance also means a non-empty value
if (isset($array[$key])) {
}
Both array_key_exists and isset more clearly communicate that the code cares about the existance of a key and not that it assumes existance and tests only for a non-empty value.
// Replace
if (empty($var)) {
}
// With
if (isset($var)) {
}
In this case you can also use isset, but in general if you need to check this there is something wrong with the code anyways. A variable should always be or not be declared in the current scope, there should not be uncertainty about it.
// Replace
if (empty($var)) {
}
// With
if ($var === null) {
}
Code is more cleary a test for the variable being null and not accidently also true when 0, false or empty string.
// Replace
if (empty($var)) {
}
// With
if ($var === 0) {
}
Communicates that variable is integer.
// Replace
if (empty($var)) {
}
// With
if ($var === false) {
}
if (!$var) {
}
Communicates that variable is boolean.
Now what if I want to test for existance and non emptiness for an array keys? Using two conditions makes this more clear.
Now what if I care about performance of empty being a language construct vs calling an internal function such as strlen or count? No worries, both strlen and count are optimized by Opcache if you prefix them with a backslash to directly call them in the global namespace.
Armed with PHP Code Sniffer and Psalm I am happy to enforce rules with my own custom plugins for either one tool.
We have a custom Psalm plugin in our Tideways code base and I have added an automatic tests for empty including a suggest for the right replacement based on the type. Its not perfect and does not yet catch all different kinds of empty usages, but its a good enough start. See this Gist for the code and how to include it in your psalm.xml.