phpconditional-operatornull-coalescing-operator

PHP null coalescing with ternary operator (again)


The following code understandably yields "dev" when $_SERVER['MODE'] is not set:

$_SERVER['MODE'] ?? null === 'production' ? 'prod' : 'dev'

That is because $_SERVER['MODE'] ?? null resolves to NULL which, of course, is not strictly equal to "production", so the right operand of the ternary expression prevails.

However, if I set $_SERVER['MODE'] to just any truthy value, things become strange. The code yields "prod"!

I do not understand why. When $_SERVER['MODE'] is set, the null coalescing resolves to whatever value it is set to. So, unless it is set to "production", the right operand of the ternary expression should still prevail. Why does it not?

Besides, if I add brackets like this:

($_SERVER['MODE'] ?? null) === 'production' ? 'prod' : 'dev'

ā€” then it works as expected. But why not without the brackets?

Related but not dupe: PHP null coalesce + ternary operators strange behavior

P.S. This confusion just costed me $40. $_SERVER['MODE'] was set to "dev" but, as the expression resolved to "prod", real AWS instances were started :D.


Solution

  • You can test the result of $_SERVER['MODE'] ?? null === 'production' pretty easily by isolating it.

    var_dump(1 ?? null === 'production'); // 1
    
    var_dump(null ?? null === 'production'); // false
    
    var_dump(null ?? 'production' === 'production'); // true
    

    That means, your operands are grouped like this unless you add the brackets:

    ( $_SERVER['MODE'] ?? (null === 'production') ) ? 'prod' : 'dev'

    If $_SERVER['MODE'] is any other value than null or false, the resulting operation will be:

    $_SERVER['MODE'] ? 'prod' : 'dev'

    So, every truthy value will evaluate to 'prod'.

    This is because the nullish coalesching operator has a higher precedence order than the ternary operator ( as can be seen here )

    I hope that makes sense.

    As a piece of advice, try to always add brackets in cases like this. The code is easier to read, maintain, and debug. And no one will go insane or lose money over issues like this one.