What's The Difference Between ?? And ?: In PHP?

A comparison and analysis of the Null Coalescing and Ternary Operator in PHP

  • By Daniyal Hamid
  • May 14, 2018
  • Comments
In This Article

In this article, we'll compare and analyze the two shorthand conditional operators in PHP, the ternary operator (?:) and the null coalescing operator (??).

?: (Ternary Operator)

The ternary operator (?:) has the following syntax:

(expr1) ? (expr2) : (expr3);

Which translates to; if expr1 evaluates to true, return expr2, otherwise return expr3. This could easily be re-written as an if/else statement like so:

if (expr1) {
    return expr2;
} else {
    return expr3;
}

Since PHP 5.3+, the ternary operator can be written in its shorter form, leaving out the middle part of the ternary operator, for a quick shorthand evaluation:

expr1 ?: expr2;

Which means, if expr1 is true, return expr1, otherwise return expr2. Here, it is important to remember that the following values are considered false in PHP:

  • Boolean false;
  • Integer 0;
  • Float 0.0;
  • String '0' or "0";
  • An empty string (i.e. '' or "");
  • An empty array (i.e. [] or array());
  • null;
  • SimpleXML objects created from empty tags.

So, whenever a falsy value is encountered the shorthand ternary operator will return the second operand. Everything that's not a falsy value is simply a truthy value and, in such an instance, shall return the first operand.

Note that the strings "00", "0.0", "\0", and "false" all evaluate to boolean true which is different from string '0' or boolean false.

Ternary Chaining:

The ternaries can be chained (i.e. it returns the first truthy value it encounters), for example:

echo 0 ?: 1 ?: 2 ?: 3; // output: 1

This is the same as writing a bunch of if/elseif/else statements, for example:

if (expr1) {
    return expr1;
} else if(expr2) {
    return expr2;
} else if(expr3) {
    return expr3;
} else {
    return expr4;
}

?? (Null Coalescing Operator)

Introduced in PHP 7, the null coalescing operator (??) has the following syntax:

expr1 ?? expr2;

Which means that expr1 is returned when expr1 exists and is NOT null; otherwise it returns expr2. This is the same as the following:

// as an if statement:
if (isset($x)) {
    return $x;
} else {
    return $y;
}

// or, as ternary operator:
return (isset($x) ? $x : $y);

// same statement as the null coalescing operator:
return $x ?? $y;

For a null coalescing operator, the only thing that matters is that the variable exists and is not null so even falsy values are given a pass.

Coalescing Chaining:

The coalescing can be chained (i.e. it returns the first defined value it encounters), for example:

$x ?? $y ?? $z ?? 'empty'; // output: 'empty'

In case there's no defined value in the coalescing chain, a "Notice: Undefined variable: ..." message is shown.

?: Vs. ??

The table below shows a side-by-side comparison of the two operators against a given expression:

Expression echo ($x ?: 'hello') echo ($x ?? 'hello')
$x = ""; 'hello' ""
$x = null; 'hello' 'hello'
$x; 'hello'
(and Notice: Undefined variable: x)
'hello'
$x = []; 'hello' []
$x = ['a', 'b']; ['a', 'b'] ['a', 'b']
$x = false; 'hello' false
$x = true; true true
$x = 1; 1 1
$x = 0; 'hello' 0
$x = -1; -1 -1
$x = '1'; '1' '1'
$x = '0'; 'hello' '0'
$x = '-1'; '-1' '-1'
$x = 'random'; 'random' 'random'
$x = new stdClass; object(stdClass) object(stdClass)