Skip to content

NullCoalescingOperatorCanBeUsed ​

info on by default quick-fix PHP ≥ 7.0

Group: Language level migration · PhpStorm name: NullCoalescingOperatorCanBeUsedInspection

Ternaries and small if constructs that pick a value when it "exists" (isset, !== null, array_key_exists, truthiness of the owning object) and a fallback otherwise can be collapsed into a single ?? expression, which is shorter and easier to read.

Example ​

php
<?php
class Box {
    /** @var int */
    public $size;
    /** @var Box|null */
    public $inner;
}
/** @var Box $box */
/** @var Box[] $boxes */

$a = isset($opts['k']) ? $opts['k'] : 5;
$b = !isset($opts['k']) ? null : $opts['k'];
$c = null === $row->id ? $fallback . 'x' : $row->id;
$d = (array_key_exists($k, $map)) ? $map[$k] : NULL;
$e = $box ? $box->size : 0;
$f = !$box ? null : $box->inner;
$g = !empty($boxes[1]) ? $boxes[1]->size : null;
$h = $box ? $box->inner : -1;            // nullable with non-null fallback
$i = $mystery ? $mystery->size : null;   // unknown type
$j = array_key_exists($k, $map) ? $map[$k] : 0;
$k2 = isset($opts['k'], $opts['j']) ? $opts['k'] : 5;
$l = isset($opts['k']) ?: 5;

function pickA($in) {
    $out = 'none';
    if (isset($in['v'])) {
        $out = $in['v'];
    }
    $n = abs($n);
    if (isset($in[$n])) { $n = $in[$n]; }      // previous value reads the target
    if ($in['w'] !== null) {
        return $in['w'];
    }
    return 'none';
}

function pickB($in) {
    if ($in) {
        $res = 1;
    } else if (isset($in)) {
        $res = $in;
    } else {
        $res = 2;
    }
    if (!(null === $in)) {
        return $in;
    } else {
        return null;
    }
}

$cb = function ($q) {
    if (isset($q)) {
        return $q;
    }
};
php
<?php
class Box {
    /** @var int */
    public $size;
    /** @var Box|null */
    public $inner;
}
/** @var Box $box */
/** @var Box[] $boxes */

$a = $opts['k'] ?? 5;
$b = $opts['k'] ?? null;
$c = $row->id ?? ($fallback . 'x');
$d = $map[$k] ?? NULL;
$e = $box->size ?? 0;
$f = $box->inner ?? null;
$g = $boxes[1]->size ?? null;
$h = $box ? $box->inner : -1;            // nullable with non-null fallback
$i = $mystery ? $mystery->size : null;   // unknown type
$j = array_key_exists($k, $map) ? $map[$k] : 0;
$k2 = isset($opts['k'], $opts['j']) ? $opts['k'] : 5;
$l = isset($opts['k']) ?: 5;

function pickA($in) {
    $out = $in['v'] ?? 'none';
    $n = abs($n);
    if (isset($in[$n])) { $n = $in[$n]; }      // previous value reads the target
    return $in['w'] ?? 'none';
}

function pickB($in) {
    if ($in) {
        $res = 1;
    } else { $res = $in ?? 2; }
    return $in ?? null;
}

$cb = function ($q) {
    return $q ?? null;
};

Reported:

  • line 11: Simplify to '$opts['k'] ?? 5' using the null coalescing operator.
  • line 12: Simplify to '$opts['k'] ?? null' using the null coalescing operator.
  • line 13: Simplify to '$row->id ?? ($fallback . 'x')' using the null coalescing operator.
  • line 14: Simplify to '$map[$k] ?? null' using the null coalescing operator.
  • line 15: Simplify to '$box->size ?? 0' using the null coalescing operator.
  • line 16: Simplify to '$box->inner ?? null' using the null coalescing operator.
  • line 17: Simplify to '$boxes[1]->size ?? null' using the null coalescing operator.
  • line 26: Simplify to '$out = $in['v'] ?? 'none'' using the null coalescing operator.
  • line 31: Simplify to 'return $in['w'] ?? 'none'' using the null coalescing operator.
  • line 40: Simplify to '$res = $in ?? 2' using the null coalescing operator.
  • line 45: Simplify to 'return $in ?? null' using the null coalescing operator.
  • line 53: Simplify to 'return $q ?? null' using the null coalescing operator.

Options ​

OptionTypeDefaultEffect
SUGGEST_SIMPLIFYING_TERNARIESbooltrueEnables Form A (ternaries).
SUGGEST_SIMPLIFYING_IFSbooltrueEnables Form B (if statements).

Both upstream fixtures set only one option explicitly, but the other one keeps its default true, so both forms are active in both runs.

Configure ​

In custos.json:

json
{
  "rules": {
    "NullCoalescingOperatorCanBeUsed": {
      "enabled": false,
      "options": {
        "SUGGEST_SIMPLIFYING_TERNARIES": true,
        "SUGGEST_SIMPLIFYING_IFS": true
      }
    }
  }
}

Suppress ​

Before the statement or declaration (or the first statement of the file), either of:

php
// @custos-ignore NullCoalescingOperatorCanBeUsed

/**
 * @noinspection NullCoalescingOperatorCanBeUsedInspection
 */

Released under the MIT License. Rule catalogue modelled on Php Inspections (EA Extended); independent clean-room implementation.