Lesson 18 of 100
Types12 min5 checksPHP 8.5

Handling Missing Values with null and Defaults

Learn how null differs from empty strings, zero and false, and how the null-coalescing operator supplies safe defaults for missing array keys.

01 · THE IDEAREAD → TRY → LEARN

What null means

In PHP, null is a type with exactly one value, and it means "no value here". It is not the same as an empty string, the number zero, the string "0", false or an empty array. Those are all real values. A user who typed nothing into a form gave you ""; a user who chose a volume of zero gave you 0; a key that was never provided gives you nothing at all. Treating these cases the same is one of the most common sources of quiet bugs.

The strict comparison === null is the dependable way to ask "is this missing?". Loose comparison with == applies type juggling. The comparison table in the manual says that when either side is null or a bool, both sides are converted to booleans, so null == false and null == 0 are both true. That is rarely what you want when you are looking for absence.

Seeing the differences

The first example runs several "empty-looking" values through a strict null check.

Example
<?php
$values = [null, '', 0, '0', false, []];
foreach ($values as $value) {
    echo json_encode($value), ' ', var_export($value === null, true), "\n";
}
Output
null true
"" false
0 false
"0" false
false false
[] false

Only the first value is identical to null. Everything else is a legitimate value that happens to be falsy.

The null-coalescing operator

The expression $a ?? $b evaluates to $a when $a exists and is not null, and to $b otherwise. It also stays silent when the left side is an undefined variable or a missing array key, much like isset(). That makes it ideal for reading optional input.

Example
<?php
$settings = ['theme' => null, 'volume' => 0, 'title' => ''];
echo json_encode([
    $settings['theme'] ?? 'light',
    $settings['volume'] ?? 5,
    $settings['title'] ?? 'Untitled',
    $settings['language'] ?? 'en',
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
["light",0,"","en"]

The null theme and the missing language both fall back to defaults. The volume of 0 and the empty title are kept, because neither is null. That is the whole point: ?? replaces only absence.

?? versus ?:

The short ternary $a ?: $b is different. It picks $b whenever $a is falsy, which includes 0, "", "0", false and []. Use it only when every falsy value really should be replaced. A retry count of 0 is a deliberate choice, so replacing it with a default would change the meaning of the configuration. Also, ?: does not suppress the warning for an undefined array key, while ?? does.

There is also the assignment form ??=, which assigns the right side only when the left side is missing or null. It is handy for filling in defaults in an array.

Example
<?php
$config = ['retries' => 0, 'name' => null];
$a = $config['retries'] ?? 3;
$b = $config['retries'] ?: 3;
$config['name'] ??= 'anonymous';
$config['mode'] ??= 'safe';
echo json_encode(['coalesce' => $a, 'elvis' => $b, 'config' => $config], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
{"coalesce":0,"elvis":3,"config":{"retries":0,"name":"anonymous","mode":"safe"}}

Notice that retries stays 0 after ??= is applied to other keys, and the ?? result is 0, while ?: produced 3.

Precedence and chaining

The ?? operator has low precedence. Mixing it with concatenation or arithmetic usually needs parentheses: write 'Mr. ' . ($name ?? 'Anonymous'), not 'Mr. ' . $name ?? 'Anonymous', because in the second form the concatenation happens first and the undefined variable is read before the default can help. You can chain it as well: $a ?? $b ?? $c returns the first operand that exists and is not null.

Common mistakes

  • Using empty() or ?: to detect a missing value, which also discards 0 and "0".
  • Comparing with == and getting a surprise because null == false.
  • Forgetting parentheses around a ?? expression inside a larger expression.
  • Using a default for a key that must be present. If missing data is an error, validate and fail loudly instead of hiding it.

Exercise contract

Write a function nicknameOrGuest(array $profile): string. If the profile has a nickname key whose value is not null, return that value unchanged. If the key is missing or its value is null, return "Guest". An empty string nickname and the string "0" are real values and must be returned as they are. The checks compare the returned strings, so do not print anything.

Recap

null means absence, and it is distinct from "", 0, "0", false and []. Test for it with === null. Use ?? to supply a default only for missing or null values, ??= to fill in defaults, and reserve ?: for cases where any falsy value should be replaced.

Before you start

Associative arrays

You’ll practice
  • Distinguish null from an empty string or zero
  • Choose defaults with the null-coalescing operator
Your task

Make nicknameOrGuest() pass all 5 checks. Run your code as often as you like, then check your answer.

exercise.phpSaved in this browserPHP 8.5
CONSOLE & CHECKS● Ready

Ready when you are

Your output will appear here.
Make it work. Then make it pass.

PHP loads on your first run. Each check starts fresh. Your code stays in this browser; clearing site data removes your progress. A check or the task looks wrong? Report a problem with this exercise.