Skip to content
Theory · Operators and comparison · lesson 7 of 8

The null operators: ?? and ?:

A program does not always have a value. A variable may never have been set, or it may hold null, "no value". Then you need a default: "guest" instead of a name, five instead of a limit.

Let's go back to the two cashiers. A customer hands over a discount coupon. The lenient cashier treats any coupon with nothing much written on it as empty: a zero, an empty string. The strict one applies the default discount only when there is no coupon at all.

In PHP the strict cashier here is ??, and the lenient one is ?:.

PHP
<?php

$discount = null;
echo $discount ?? 5, "\n"; // 5
echo $coupon ?? 'none', "\n"; // none
$discount = 0;
echo $discount ?? 5, "\n"; // 0
echo $discount ?: 5, "\n"; // 5

Let's go through the program line by line:

  1. $discount ?? 5 prints 5: $discount holds null.
  2. $coupon ?? 'none' prints none: there is no variable $coupon at all, and PHP gives no warning.
  3. After $discount = 0 the expression $discount ?? 5 prints 0: zero is a real value, not null.
  4. $discount ?: 5 prints 5: for ?: zero counts as empty.

The ?? operator

The null coalescing operator is written $a ?? $b:

  • if $a is set and is not null, the result is $a;
  • otherwise the result is $b.

?? first checks whether the variable exists and only then reads it. That is why it stays silent on a variable that was never set, although a plain read of $coupon would give Warning: Undefined variable $coupon.

A chain of ??

You can put ?? operators one after another: $a ?? $b ?? 'x'. PHP checks from left to right and takes the first value that is set and is not null. If $a and $b are both null, the result is 'x'.

The ??= operator

$limit ??= 20 writes 20 into $limit only if the variable is not set or is null:

PHP
$limit = null;
$limit ??= 20;
$page = 0;
$page ??= 1;
echo $limit, ' ', $page, "\n"; // 20 0

$limit now holds 20, while $page stays 0: zero is set and is not null.

The ?: operator

$a ?: $b takes $b when $a turns into false. Among the values you know so far, these turn into false:

  • false and null;
  • 0 and 0.0;
  • the empty string '' and the string '0'.

These are the same values that (bool) turns into false. For ?: an empty string in $name means "no name", so $name ?: 'guest' gives guest.

But ?: reads the variable as usual. If it was never set, PHP gives a warning, as with any read of a variable that was never set.

Interviewers often ask how ?? differs from ?:. The answer:

  • ?? replaces only null and a variable that was never set, and it does so without a warning;
  • ?: replaces everything that turns into false, including 0 and '';
  • ?: reads the variable as usual, and a variable that was never set gives a Warning.

The cashier picture simplifies here. A real cashier will ask what you meant, but ?: does not ask: to it zero is always empty, even when it is an honest price of zero. When 0 or '' are valid values, use ??.

Common mistake

A default name is supplied with ?:, but nobody set the variable:

PHP
echo $nickname ?: 'guest', "\n"; // ✗
TEXT
Warning: Undefined variable $nickname

PHP prints the warning and then guest: ?: reads $nickname as an ordinary variable, and it does not exist. The program keeps running, but the warning points to a bug in the code. Replace ?: with ??: $nickname ?? 'guest' prints guest without a warning.

Key points

  • ?? supplies the right side when the left one is missing or holds null, and it gives no warning.
  • ?: supplies the right side for everything that turns into false: 0, '', '0', null.
  • $x ??= 20 writes 20 only if $x is not set or is null.
  • When zero or an empty string is a valid value, choose ??.