C#'s null coalescing operator (??) in PHP

2019-01-06 17:11发布

Is there a ternary operator or the like in PHP that acts like ?? of C#?

?? in C# is clean and shorter, but in PHP you have to do something like:

// This is absolutely okay except that $_REQUEST['test'] is kind of redundant.
echo isset($_REQUEST['test'])? $_REQUEST['test'] : 'hi';

// This is perfect! Shorter and cleaner, but only in this situation.
echo null? : 'replacement if empty';

// This line gives error when $_REQUEST['test'] is NOT set.
echo $_REQUEST['test']?: 'hi';

6条回答
霸刀☆藐视天下
2楼-- · 2019-01-06 17:17

PHP 7 adds the null coalesce operator:

// Fetches the value of $_GET['user'] and returns 'nobody'
// if it does not exist.
$username = $_GET['user'] ?? 'nobody';
// This is equivalent to:
$username = isset($_GET['user']) ? $_GET['user'] : 'nobody';

You could also look at short way of writing php's ternary operator ?: (php >=5.3 only)

// Example usage for: Short Ternary Operator
$action = $_POST['action'] ?: 'default';

// The above is identical to
$action = $_POST['action'] ? $_POST['action'] : 'default';

And your comparison to C# is not fair. "in PHP you have to do something like" - In C# you will also have a runtime error if you try to access a non-existent array/dictionary item.

查看更多
对你真心纯属浪费
3楼-- · 2019-01-06 17:22

?? is binary in C#, not ternary. And it has no equivalence in PHP prior to PHP 7.

查看更多
我只想做你的唯一
4楼-- · 2019-01-06 17:29

Prior to PHP 7, there isn't. If you need to involve isset, the pattern to use is isset($var) ? $var : null. There's no ?: operator that includes the characteristics of isset.

查看更多
一纸荒年 Trace。
5楼-- · 2019-01-06 17:30

An identical operator doesn't exist as of PHP 5.6, but you can make a function that behaves similarly.

/**
 * Returns the first entry that passes an isset() test.
 *
 * Each entry can either be a single value: $value, or an array-key pair:
 * $array, $key.  If all entries fail isset(), or no entries are passed,
 * then first() will return null.
 *
 * $array must be an array that passes isset() on its own, or it will be
 * treated as a standalone $value.  $key must be a valid array key, or
 * both $array and $key will be treated as standalone $value entries. To
 * be considered a valid key, $key must pass:
 *
 *     is_null($key) || is_string($key) || is_int($key) || is_float($key)
 *         || is_bool($key)
 *
 * If $value is an array, it must be the last entry, the following entry
 * must be a valid array-key pair, or the following entry's $value must
 * not be a valid $key.  Otherwise, $value and the immediately following
 * $value will be treated as an array-key pair's $array and $key,
 * respectfully.  See above for $key validity tests.
 */
function first(/* [(array $array, $key) | $value]... */)
{
    $count = func_num_args();

    for ($i = 0; $i < $count - 1; $i++)
    {
        $arg = func_get_arg($i);

        if (!isset($arg))
        {
            continue;
        }

        if (is_array($arg))
        {
            $key = func_get_arg($i + 1);

            if (is_null($key) || is_string($key) || is_int($key) || is_float($key) || is_bool($key))
            {
                if (isset($arg[$key]))
                {
                    return $arg[$key];
                }

                $i++;
                continue;
            }
        }

        return $arg;
    }

    if ($i < $count)
    {
        return func_get_arg($i);
    }

    return null;
}

Usage:

$option = first($option_override, $_REQUEST, 'option', $_SESSION, 'option', false);

This would try each variable until it finds one that satisfies isset():

  1. $option_override
  2. $_REQUEST['option']
  3. $_SESSION['option']
  4. false

If 4 weren't there, it would default to null.

Note: There's a simpler implementation that uses references, but it has the side effect of setting the tested item to null if it doesn't already exist. This can be problematic when the size or truthiness of an array matters.

查看更多
Luminary・发光体
6楼-- · 2019-01-06 17:33

I use function. Obviously it is not operator, but seems cleaner than your approach:

function isset_or(&$check, $alternate = NULL)
{
    return (isset($check)) ? $check : $alternate;
}

Usage:

isset_or($_REQUEST['test'],'hi');
查看更多
我命由我不由天
7楼-- · 2019-01-06 17:34

The Null Coalesce Operator, (??) has been accepted and implemented in PHP 7. It differs from the short ternary operator (?:) in that ?? will suppress the E_NOTICE that would otherwise occur when attempting to access an array where it doesn't have a key. The first example in the RFC gives:

$username = $_GET['user'] ?? 'nobody';
// equivalent to: $username = isset($_GET['user']) ? $_GET['user'] : 'nobody';

Notice that the ?? operator does not require the manual application of isset to prevent the E_NOTICE.

查看更多
登录 后发表回答