Question

PHP Elvis Operator (?:) vs Null Coalescing Operator (??)

phpconditional-operatornull-coalescing-operatorelvis-operator

Question

In PHP, what is the difference between the short ternary operator (?:) and the null coalescing operator (??)?

When do these two expressions behave differently, and when do they produce the same result?

$a ?: $b

$a ?? $b

Short Answer

By the end of this page, you will understand how PHP's short ternary operator ?: and null coalescing operator ?? decide whether to return the left or right value. You will learn the key difference between falsy checks and null-or-undefined checks, see where they behave the same, and know which one to choose in real PHP code.

Concept

The two operators look similar, but they solve different problems.

  • ?: is the short ternary operator, often called the Elvis operator.
  • ?? is the null coalescing operator.

Their difference comes from what they test.

?: checks for truthiness

$result = $a ?: $b;

This means:

$result = $a ? $a : $b;

So PHP evaluates $a as a boolean.

If $a is truthy, the result is $a. If $a is falsy, the result is $b.

In PHP, common falsy values include:

  • false
  • 0
  • 0.0
  • ""
  • "0"
  • []
  • null

?? checks for null or missing values

$result = $a ?? $b;

This means roughly:

$result = isset($a) ? $a : $b;

So ?? does not care whether $a is truthy or falsy. It only cares whether $a:

  • exists, and
  • is not null

If $a is set and not null, PHP returns $a. If $a is undefined or null, PHP returns $b.

Why this matters

In real programs, values like 0, "", or false are often valid data.

For example:

  • a quantity of 0
  • an empty search string ""
  • a boolean setting false

If you use ?:, those values are treated as "use the fallback". If you use ??, those values are preserved.

That makes ?? especially useful for:

  • request input
  • configuration values
  • optional array keys
  • default values for variables that may be missing

Use ?: when you want a fallback for any falsy value. Use ?? when you want a fallback only for null or undefined values.

Mental Model

Think of the two operators as two different gatekeepers.

?: is a strict "does this look usable?" gatekeeper

It looks at the value and says:

  • "If this is truthy, keep it."
  • "If this is falsy, replace it."

So values like 0 or "" get rejected, even if they are meaningful.

?? is a "is anything actually missing?" gatekeeper

It asks:

  • "Is there a value here?"
  • "Is it not null?"

If the answer is yes, it keeps the value, even if that value is 0, false, or "".

Simple analogy

Imagine filling out a form:

  • ?: says: "This field looks empty or weak, so I will use the backup."
  • ?? says: "I only use the backup if the field was not filled in at all, or was explicitly null."

That is the core difference: falsy vs missing/null.

Take Quiz

Syntax and Examples

Core syntax

$a ?: $b
$a ?? $b

Expanded forms

$a ?: $b   // same as: $a ? $a : $b
$a ?? $b   // similar to: isset($a) ? $a : $b

Example 1: value is 0

$a = 0;
$b = 100;

echo $a ?: $b;  // 100
echo "\n";
echo $a ?? $b;  // 0

Why?

  • 0 is falsy, so ?: returns $b
  • 0 is not null, so ?? returns $a

Example 2: value is null

$a = null;
$b = 'fallback';

echo $a ?: $b;  // fallback
echo "\n";
echo $a ?? $b;  // fallback

Here they behave the same because null is both:

  • falsy
  • considered missing by ??

Example 3: value is an empty string

$a = "";
$b = "default";

echo $a ?: $b;  // default
echo "\n";
echo $a ?? $b;  // ""

Why?

  • "" is falsy, so ?: uses the fallback
  • "" is set and not null, so ?? keeps it

Example 4: undefined variable

// $a is not defined
$b = 'fallback';

$result1 = $a ?? $b; // fallback

This is a common use case for ??.

With ?:, using an undefined variable is problematic because PHP must evaluate $a directly.

// $a is not defined
$result2 = $a ?: $b; // may raise a notice/warning depending on PHP version/settings

Example 5: boolean false

$a = false;
$b = true;

var_dump($a ?: $b); // bool(true)
var_dump($a ?? $b); // bool(false)

This is one of the most important practical differences.

Step by Step Execution

Consider this code:

$a = 0;
$b = 5;

$x = $a ?: $b;
$y = $a ?? $b;

Step-by-step for $x = $a ?: $b;

  1. PHP reads $a.
  2. PHP converts $a to a boolean for the condition.
  3. $a is 0, which is falsy.
  4. Because the condition is false, PHP returns $b.
  5. $x becomes 5.

Step-by-step for $y = $a ?? $b;

  1. PHP checks whether $a is set and not null.
  2. $a exists.
  3. $a is 0, not null.
  4. PHP keeps $a.
  5. $y becomes 0.

Final values

var_dump($x); // int(5)
var_dump($y); // int(0)

Another trace with null

$a = null;
$b = 5;

$x = $a ?: $b;
$y = $a ?? $b;
  • ?: sees null as falsy, so $x becomes 5
  • ?? sees null as missing, so $y becomes 5

In this case, both produce the same result.

Real World Use Cases

Use ?? for optional input and defaults

Request parameters

$page = $_GET['page'] ?? 1;
$search = $_GET['search'] ?? '';

This is useful because the key may not exist at all.

Configuration values

$host = $config['host'] ?? 'localhost';
$port = $config['port'] ?? 3306;

If the config key is missing or null, a default is used.

Nested data access

$username = $user['profile']['username'] ?? 'guest';

Use ?: when any falsy value should trigger a fallback

Display label fallback

$label = trim($input) ?: 'Untitled';

If the trimmed input becomes an empty string, use 'Untitled'.

Optional computed result

$slug = generateSlug($title) ?: 'default-slug';

If slug generation returns an empty string, use a fallback.

Post-validation cleanup

$name = $name ?: 'Anonymous';

This only makes sense if values like "", false, or 0 should all be treated as unusable.

A practical rule

  • Use ?? for missing data
  • Use ?: for empty/falsy data
Take Quiz

Real Codebase Usage

In real PHP projects, developers often use these operators in predictable patterns.

Pattern: safe defaults from arrays and request data

$sort = $_GET['sort'] ?? 'created_at';
$limit = $_GET['limit'] ?? 20;

This avoids notices for missing keys and keeps valid falsy values if they exist.

Pattern: environment and configuration fallback

$env = $_ENV['APP_ENV'] ?? 'production';
$debug = $config['debug'] ?? false;

This is common in framework bootstrapping and config loading.

Pattern: normalize output after processing

$title = trim($title) ?: 'Untitled';

After transforming data, ?: is useful when an empty result should be replaced.

Pattern: guard clause with defaults

function renderTitle(?string $title): string {
    return $title ?? 'Default Title';
}

If null means "no value provided," ?? is the right choice.

Pattern: preserving meaningful false and 0

$isEnabled = $settings['enabled'] ?? true;
$retryCount = $options['retries'] ?? 3;

If the actual stored value is false or 0, ?? keeps it. That is usually what you want in configuration code.

Pattern: fallback after validation

$nickname = trim($nickname);
$nickname = $nickname ?: 'guest';

Here an empty string after trimming should be replaced, so ?: fits.

Good team habit

A lot of bugs come from choosing ?: when 0, false, or "" are valid values. In production code, ?? is often safer for defaults.

Common Mistakes

Mistake 1: using ?: when 0 is a valid value

$quantity = 0;
echo $quantity ?: 10; // 10

If 0 is a meaningful value, this is wrong.

Better

echo $quantity ?? 10; // 0

Mistake 2: using ?: with false when false is a real setting

$enabled = false;
$result = $enabled ?: true; // true

This overwrites a valid false value.

Better

$result = $enabled ?? true; // false

Mistake 3: expecting ?? to treat empty strings as missing

$name = "";
echo $name ?? 'Anonymous'; // ""

If you want empty strings to fall back too, ?? is not enough.

Better

echo $name ?: 'Anonymous'; // Anonymous

Or make the rule explicit:

echo trim($name) === '' ? 'Anonymous' : $name;

Mistake 4: forgetting that undefined variables behave differently

// $value not defined
$result = $value ?: 'fallback';

This can raise notices or warnings because $value must be evaluated.

Better

$result = $value ?? 'fallback';

Mistake 5: assuming ?: and ?? are interchangeable

They are only the same when the left side is both:

  • falsy, and
  • null

For example:

$a = null;
var_dump($a ?: 'x'); // x
var_dump($a ?? 'x'); // x

But they differ for many other values:

$a = 0;
var_dump($a ?: 'x'); // x
var_dump($a ?? 'x'); // 0

Comparisons

OperatorWhat it checksReturns right side when left side is...Preserves 0Preserves falsePreserves ""Safe for undefined variable
?:TruthinessfalsyNoNoNoNo
??isset()-style null checkundefined or nullYesYesYesYes

Same result cases

They produce the same result when the left side is:

  • null

Example:

$a = null;
$b = 'fallback';

var_dump($a ?: $b); // fallback
var_dump($a ?? $b); // fallback

Different result cases

They behave differently when the left side is a falsy value that is not null.

Left value$a ?: $b$a ?? $b
0$b0
false$bfalse
""$b""
"0"$b"0"
[]$b[]

Compared with full ternary

ExpressionMeaning
$a ? $x : $yIf $a is truthy, return $x, else $y
$a ?: $bIf $a is truthy, return $a, else $b
$a ?? $bIf $a exists and is not null, return $a, else $b
Take Quiz

Cheat Sheet

$a ?: $b   // uses $b if $a is falsy
$a ?? $b   // uses $b if $a is undefined or null

Use ?: when

  • you want to reject all falsy values
  • empty strings should fall back
  • 0 and false should also fall back

Use ?? when

  • a variable or array key may be missing
  • null should trigger the default
  • 0, false, and "" are valid values

Falsy values in PHP

These make ?: choose the right side:

  • false
  • 0
  • 0.0
  • ""
  • "0"
  • []
  • null

Quick examples

0 ?: 5        // 5
0 ?? 5        // 0

false ?: true // true
false ?? true // false

'' ?: 'x'     // 'x'
'' ?? 'x'     // ''

null ?: 'x'   // 'x'
null ?? 'x'   // 'x'

Rule of thumb

  • ?: = fallback for falsy
  • ?? = fallback for null or missing

FAQ

What is the difference between ?: and ?? in PHP?

?: checks whether the left value is truthy. ?? checks whether the left value exists and is not null.

Does ?? behave like isset()?

Yes. a ?? b is roughly equivalent to isset($a) ? $a : $b.

Does ?: treat 0 as empty?

Yes. Since 0 is falsy in PHP, ?: will use the fallback value.

When do ?: and ?? return the same result?

They return the same result when the left side is null.

Which operator should I use for $_GET or $_POST values?

Usually ??, because request keys may be missing and values like 0 or "" may still be valid.

Why does ?: fail with undefined variables?

Because PHP must evaluate the left side directly. ?? is designed to handle undefined variables or missing array keys safely.

Is ?? better than ?:?

Not always. ?? is better for missing or null values. ?: is better when any falsy value should trigger a fallback.

Take Quiz

Mini Project

Description

Build a small PHP script that reads optional user settings and displays final values with sensible defaults. This project demonstrates the practical difference between ?: and ?? when handling missing data, empty strings, zero values, and boolean flags.

Goal

Create a script that shows when to preserve valid falsy values with ?? and when to replace empty-style values with ?:.

Requirements

  1. Create variables representing optional settings such as username, page number, and dark mode.
  2. Use ?? for values that may be missing or null.
  3. Use ?: for a display value where an empty string should fall back.
  4. Print the final resolved values so the difference is visible.
Take Quiz

Keep learning

Related questions

View more