null, isset and empty
The condition if ($x) asks whether a value is truthy. But sometimes there is no variable $x in the program at all: nobody assigned it a value, or its name has a typo. What does the condition say then?
<?php
if ($nickname) { // ✗
echo 'Hi, ', $nickname, "\n";
}
echo 'next', "\n";Warning: Undefined variable $nicknameThe variable $nickname never got a value. PHP issues a warning, reads it as null, skips the branch and prints next. The program keeps running, but the warning points to a bug in the code, and it must not stay there.
Imagine you are looking for a sign with a town's name at the fork. There are three possible situations:
- there is no sign at all: the variable is not defined;
- the sign hangs there but is blank: the variable holds
null; - something is written on the sign: the variable holds a value.
PHP has three tools for these checks, and they answer different questions.
Three checks
isset
isset($x) asks whether there is a sign with something written on it. The answer is true when the variable exists and its value is not null.
$city = 'Paris';
$phone = null;
var_dump(isset($city)); // bool(true)
var_dump(isset($phone)); // bool(false)
var_dump(isset($email)); // bool(false)Let's go through it line by line:
$cityholds a string, soissetgivestrue.$phoneholdsnull, andissetgivesfalse.$emailis not defined, andissetgivesfalsewithout any warning.
Why is there no warning? isset is not a function but a language construct: a part of the language itself that checks the variable directly instead of receiving its value like a function. That is why a missing variable does not bother it.
Here the analogy and PHP part ways. At a fork, a blank sign is visible at once. But isset does not tell it from a missing one: for $phone = null and for an undefined variable alike, it gives false.
empty
empty($x) asks whether the sign is blank or missing altogether. The answer is true when the variable is missing or its value is falsy—from the same list as in a condition. In effect, empty($x) works like !isset($x) || !$x.
$count = 0;
$title = 'News';
var_dump(empty($count)); // bool(true)
var_dump(empty($title)); // bool(false)
var_dump(empty($missing)); // bool(true)Let's go through it line by line:
0is a falsy value, soempty($count)givestrue, even though the variable is set.$titleholds a non-empty string, andemptygivesfalse.$missingis not defined:emptyis a language construct too, and it quietly givestrue.
is_null
is_null($x) asks whether the sign is blank, that is, whether the value is exactly null. The answer is true only for null. For 0 and '' it gives false, because those are real values.
But is_null is an ordinary function. To pass it a value, PHP first reads the variable, and for a missing one it issues the same warning as if does:
Warning: Undefined variable $emailAfter the warning, is_null($email) still returns true: PHP reads a missing variable as null.
Comparing the three checks
Value of $x | isset($x) | empty($x) |
|---|---|---|
| no variable | false | true |
null | false | true |
0 or '' | true | true |
'Anna' | true | false |
Interviewers often ask: "How do isset, empty and is_null differ?" The answer:
isset: the variable exists and is notnull, with no warnings;empty: the variable is missing or its value is falsy, with no warnings either;is_null: the value is exactlynull; it is a function, and it warns on a missing variable.
The ?? operator
As you already know, $a ?? $b gives $a when it is set and not null, and $b otherwise. It is isset in the form of an expression: $name = $nickname ?? 'guest'; works like isset($nickname) ? $nickname : 'guest' and also gets by without warnings.
Common mistake
A quantity from a form arrived as the string '0', and its presence was checked with empty:
$quantity = '0';
if (empty($quantity)) { // ✗
echo 'enter a quantity', "\n";
} else {
echo 'ordered: ', $quantity, "\n";
}The program prints enter a quantity, even though the person entered zero: '0' is a falsy value, and empty treats it as blank. To tell "not filled in" from zero, check for absence and for the empty string separately: if (!isset($quantity) || $quantity === '').
Key points
isset($x)givestruewhen the variable exists and is notnull, and it never warns.empty($x)givestruefor a missing variable and for any falsy value,0and'0'included.is_null($x)checks only fornull; it is a function, and it issues a warning on an undefined variable.$a ?? $bisissetin the form of an expression.