Null Coalescing & Spaceship
Two operators added in relatively recent PHP versions solve two
very different problems, but both tend to appear side by side in
modern codebases: the null coalescing operator ?? (and its
assignment form ??=) for supplying default values cleanly, and
the spaceship operator <=> for writing compact three-way
comparisons, most often inside sorting callbacks.
The null coalescing operator: ??
$a ?? $b evaluates to $a if $a exists and is not null; otherwise it evaluates to $b. Crucially, ?? does not raise a warning if $a is completely undefined — it behaves as if you had wrapped the check in isset() first, which makes it the standard tool for reading optional array keys or request parameters.
?? for default values
<?php
$settings = ["theme" => "dark"];
$theme = $settings["theme"] ?? "light"; // "dark" - key exists
$fontSize = $settings["fontSize"] ?? 14; // 14 - key missing, no warning
echo "{$theme}, {$fontSize}px";dark, 14px
?? vs the isset() ternary
Before PHP 7, the common pattern was a verbose ternary built on isset(). ?? collapses that entire pattern into one clean expression and, unlike a plain ternary on the value itself, it specifically checks for "set and not null" rather than truthiness — so a value of 0, "", or false is left alone, not replaced.
?? replaces the isset() ternary
<?php $page = isset($_GET['page']) ? $_GET['page'] : 1; // old, verbose $page = $_GET['page'] ?? 1; // same result, cleaner $discount = 0; // a legitimate value, not "missing" $applied = $discount ?? 10; // 0 - ?? only replaces null/unset $fallback = $discount ?: 10; // 10 - ?: replaces any falsy value, including 0
Chaining ?? and reading nested data
?? can be chained across several fallbacks, and it also short circuits on undefined nested array keys without raising warnings — which is exactly the situation where directly indexing nested arrays tends to blow up.
Chaining and nested keys
<?php
$request = ["user" => ["name" => "Sam"]];
$city = $request["user"]["address"]["city"] ?? "Unknown"; // safe, no warning
$name = $request["user"]["nickname"] ?? $request["user"]["name"] ?? "Guest";
echo "{$city}, {$name}";Unknown, Sam
The null coalescing assignment operator: ??=
$a ??= $b is shorthand for $a = $a ?? $b: assign $b into $a only if $a is currently null or does not exist. It reads naturally as "fill this in if it's missing."
??= for filling in defaults
<?php $options = []; $options["retries"] ??= 3; $options["retries"] ??= 5; // no effect, already set echo $options["retries"]; // 3
3
The spaceship operator: <=>
$a <=> $b returns -1 when $a is less than $b, 0 when they
are equal, and 1 when $a is greater than $b. It works on
numbers, strings, and arrays using the same rules PHP already
applies for </> comparisons. Its real value shows up in
sorting: any function that expects a comparator — most notably
usort() — wants exactly this -1/0/1 contract.
Spaceship in a usort callback
<?php
$people = [
["name" => "Zoe", "age" => 25],
["name" => "Amir", "age" => 31],
["name" => "Priya", "age" => 19],
];
usort($people, fn($a, $b) => $a["age"] <=> $b["age"]);
foreach ($people as $person) {
echo "{$person['name']} ({$person['age']})\n";
}Priya (19) Zoe (25) Amir (31)
Before the spaceship operator, the same comparator was usually
written as a longer conditional chain returning -1, 0, or 1
by hand. <=> produces exactly the same result in a fraction of
the code, and it composes nicely for multi-key sorts.
Sorting by multiple keys
<?php
$products = [
["category" => "B", "price" => 20],
["category" => "A", "price" => 50],
["category" => "A", "price" => 10],
];
usort($products, function ($a, $b) {
return $a["category"] <=> $b["category"]
?: $a["price"] <=> $b["price"];
});
foreach ($products as $p) {
echo "{$p['category']} - {$p['price']}\n";
}A - 10 A - 50 B - 20
??returns the left side unless it is null/unset, then falls back to the right side.??=assigns only when the target is null or unset.??differs from?:, which falls back on any falsy value, not just null.<=>returns -1, 0, or 1 and is the natural fit forusort()/uasort()callbacks.