PHP ternary operator vs null coalescing operator

后端 未结 13 1702
南笙
南笙 2020-11-22 15:58

Can someone explain the differences between ternary operator shorthand (?:) and null coalescing operator (??) in PHP?

When do they behave d

相关标签:
13条回答
  • 2020-11-22 16:33

    When using the superglobals like $_GET or $_REQUEST you should be aware that they could be an empty string. In this specal case this example

    $username = $_GET['user'] ?? 'nobody';
    

    will fail because the value of $username now is an empty string.

    So when using $_GET or even $_REQUEST you should use the ternary operator instead like this:

    $username = (!empty($_GET['user'])?$_GET['user']:'nobody';
    

    Now the value of $username is 'nobody' as expected.

    0 讨论(0)
  • 2020-11-22 16:34

    The other answers goes deep and give great explanations. For those who look for quick answer,

    $a ?: 'fallback' is $a ? $a : 'fallback'

    while

    $a ?? 'fallback' is $a = isset($a) ? $a : 'fallback'


    The main difference would be when the left operator is either:

    • A falsy value that is NOT null (0, '', false, [], ...)
    • An undefined variable
    0 讨论(0)
  • 2020-11-22 16:38
    class a
    {
        public $a = 'aaa';
    }
    
    $a = new a();
    
    echo $a->a;  // Writes 'aaa'
    echo $a->b;  // Notice: Undefined property: a::$b
    
    echo $a->a ?? '$a->a does not exists';  // Writes 'aaa'
    
    // Does not throw an error although $a->b does not exist.
    echo $a->b ?? '$a->b does not exist.';  // Writes $a->b does not exist.
    
    // Does not throw an error although $a->b and also $a->b->c does not exist.
    echo $a->b->c ?? '$a->b->c does not exist.';  // Writes $a->b->c does not exist.
    
    0 讨论(0)
  • 2020-11-22 16:40

    When your first argument is null, they're basically the same except that the null coalescing won't output an E_NOTICE when you have an undefined variable. The PHP 7.0 migration docs has this to say:

    The null coalescing operator (??) has been added as syntactic sugar for the common case of needing to use a ternary in conjunction with isset(). It returns its first operand if it exists and is not NULL; otherwise it returns its second operand.

    Here's some example code to demonstrate this:

    <?php
    
    $a = null;
    
    print $a ?? 'b'; // b
    print "\n";
    
    print $a ?: 'b'; // b
    print "\n";
    
    print $c ?? 'a'; // a
    print "\n";
    
    print $c ?: 'a'; // Notice: Undefined variable: c in /in/apAIb on line 14
    print "\n";
    
    $b = array('a' => null);
    
    print $b['a'] ?? 'd'; // d
    print "\n";
    
    print $b['a'] ?: 'd'; // d
    print "\n";
    
    print $b['c'] ?? 'e'; // e
    print "\n";
    
    print $b['c'] ?: 'e'; // Notice: Undefined index: c in /in/apAIb on line 33
    print "\n";
    

    The lines that have the notice are the ones where I'm using the shorthand ternary operator as opposed to the null coalescing operator. However, even with the notice, PHP will give the same response back.

    Execute the code: https://3v4l.org/McavC

    Of course, this is always assuming the first argument is null. Once it's no longer null, then you end up with differences in that the ?? operator would always return the first argument while the ?: shorthand would only if the first argument was truthy, and that relies on how PHP would type-cast things to a boolean.

    So:

    $a = false ?? 'f'; // false
    $b = false ?: 'g'; // 'g'
    

    would then have $a be equal to false and $b equal to 'g'.

    0 讨论(0)
  • 2020-11-22 16:42

    It seems there are pros and cons to using either ?? or ?:. The pro to using ?: is that it evaluates false and null and "" the same. The con is that it reports an E_NOTICE if the preceding argument is null. With ?? the pro is that there is no E_NOTICE, but the con is that it does not evaluate false and null the same. In my experience, I have seen people begin using null and false interchangeably but then they eventually resort to modifying their code to be consistent with using either null or false, but not both. An alternative is to create a more elaborate ternary condition: (isset($something) or !$something) ? $something : $something_else.

    The following is an example of the difference of using the ?? operator using both null and false:

    $false = null;
    $var = $false ?? "true";
    echo $var . "---<br>";//returns: true---
    
    $false = false;
    $var = $false ?? "true";
    echo $var . "---<br>"; //returns: ---
    

    By elaborating on the ternary operator however, we can make a false or empty string "" behave as if it were a null without throwing an e_notice:

    $false = null;
    $var = (isset($false) or !$false) ? $false : "true";
    echo $var . "---<br>";//returns: ---
    
    $false = false;
    $var = (isset($false) or !$false) ? $false : "true";
    echo $var . "---<br>";//returns: ---
    
    $false = "";
    $var = (isset($false) or !$false) ? $false : "true";
    echo $var . "---<br>";//returns: ---
    
    $false = true;
    $var = (isset($false) or !$false) ? $false : "true";
    echo $var . "---<br>";//returns: 1---
    

    Personally, I think it would be really nice if a future rev of PHP included another new operator: :? that replaced the above syntax. ie: // $var = $false :? "true"; That syntax would evaluate null, false, and "" equally and not throw an E_NOTICE...

    0 讨论(0)
  • 2020-11-22 16:44

    Both are shorthands for longer expressions.

    ?: is short for $a ? $a : $b. This expression will evaluate to $a if $a evaluates to TRUE.

    ?? is short for isset($a) ? $a : $b. This expression will evaluate to $a if $a is set and not null.

    Their use cases overlaps when $a is undefined or null. When $a is undefined ?? will not produce an E_NOTICE, but the results are the same. When $a is null the result is the same.

    0 讨论(0)
提交回复
热议问题