Null Coalescing ?? and ??=

?? returns the first value that exists and isn't null; ??= assigns only when the target is null. Both are silent about undefined keys.

The null coalescing operator ?? is the polite one: it reads a value that might not exist without ever emitting a warning. It's the modern replacement for sprawling isset() ladders.

Chaining and the ??= form

<?php
$config = [];
// first non-null wins
$timeout = $config['timeout'] ?? $env['TIMEOUT'] ?? 30;

// ??= sets a default only if the key is missing/null
$config['retries'] ??= 3;
echo $timeout;            // 30
echo $config['retries'];  // 3

Remember the boundary: ?? only cares about null (and undefined). An empty string or 0 passes through untouched — that's usually exactly what you want, and where it differs from the short ternary ?:.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Safely read deeply nested JSON config keys (e.g. $cfg['db']['host'] ?? 'localhost') without isset checks.
  • Use ??= to lazily populate a cache array entry the first time a key is accessed.
  • Chain multiple fallback sources for a setting: env var ?? config file value ?? hard-coded default.

More examples

Deep nested key access

?? suppresses undefined-index notices and returns the fallback; it works at every depth of nesting.

Example · php
<?php
$config = ['database' => ['port' => 5432]];

$host    = $config['database']['host']    ?? 'localhost';
$port    = $config['database']['port']    ?? 3306;
$timeout = $config['database']['timeout'] ?? 30;

echo "$host:$port (timeout $timeout)"; // localhost:5432 (timeout 30)

??= for lazy initialisation

??= only calls the right-hand side when the variable is null or unset, making it ideal for one-time cache population.

Example · php
<?php
$cache = [];

function expensiveLoad(string $key): string {
    echo "Loading $key\n";
    return strtoupper($key);
}

$cache['foo'] ??= expensiveLoad('foo'); // runs
$cache['foo'] ??= expensiveLoad('foo'); // skipped

echo $cache['foo']; // FOO

Chained fallback sources

Chaining ?: and ?? creates a priority-ordered fallback: env variable, then config file, then hard-coded default.

Example · php
<?php
$appConfig = ['log_level' => 'info'];

$level = getenv('LOG_LEVEL')
    ?: ($appConfig['log_level'] ?? 'warning');

echo $level; // 'info' (from appConfig; env not set)

Discussion

  • Be the first to comment on this lesson.