ajf

Andrea Faulds

Contents

PHP RFC: Null Coalesce Operator

Introduction

PHP is a web-focussed programming language, so processing user data is a frequent activity. In such processing it is common to check for something's existence, and if it doesn't exist, use a default value. Yet the simplest way to do this, something along the lines of isset($_GET['mykey']) ? $_GET['mykey'] : "", is unnecessarily cumbersome. The short ternary operator, ?: provides a way to do this much more conveniently: $_GET['mykey'] ?: "". However, this is not good practice, as if the value does not exist it will raise an E_NOTICE. Because of these issues, some sort of ifsetor() operator or a modification to ?:'s behaviour to make this common pattern easier has been a frequent request (See References).

Proposal

The coalesce, or ??, operator is added, which returns the result of its first operand if it exists and is not NULL, or else its second operand. This means the $_GET['mykey'] ?? "" is completely safe and will not raise an E_NOTICE. Some examples of its use:

// Fetches the request parameter user and results in 'nobody' if it doesn't exist
$username = $_GET['user'] ?? 'nobody';
// equivalent to: $username = isset($_GET['user']) ? $_GET['user'] : 'nobody';
 
// Calls a hypothetical model-getting function, and uses the provided default if it fails
$model = Model::get($id) ?? $default_model;
// equivalent to: if (($model = Model::get($id)) === NULL) { $model = $default_model; }
 
// Parse JSON image metadata, and if the width is missing, assume 100
$imageData = json_decode(file_get_contents('php://input'));
$width = $imageData['width'] ?? 100;
// equivalent to: $width = isset($imageData['width']) ? $imageData['width'] : 100;

It can even be chained:

$x = NULL;
$y = NULL;
$z = 3;
var_dump($x ?? $y ?? $z); // int(3)
 
$x = ["yarr" => "meaningful_value"];
var_dump($x["aharr"] ?? $x["waharr"] ?? $x["yarr"]); // string(16) "meaningful_value"

This example demonstrates the precedence relative to the ternary operator and the boolean or operator, which is the same as C#:

var_dump(2 ?? 3 ? 4 : 5);      // (2 ?? 3) ? 4 : 5        => int(4)
var_dump(0 || 2 ?? 3 ? 4 : 5); // ((0 || 2) ?? 3) ? 4 : 5 => int(4)

This example demonstrates how it is a short-circuiting operator:

function foo() {
    echo "executed!", PHP_EOL;
}
var_dump(true ?? foo()); // outputs bool(true), "executed!" does not appear as it short-circuited

Proposed PHP Version(s)

This proposed for the next PHP x, which at the time of this writing would be PHP 7.

Patches and Tests

A pull request with a working implementation and test, targeting master, is here: https://github.com/php/php-src/pull/824

The original patch was graciously provided by Nikita Popov.

Implementation

References

Rejected Features

Keep this updated with features that were discussed on the mail lists.

Errata

Versions

Version Changed Date
6 Added Errata
0.2.3 Added short-circuit example
0.2.2 Added precedence example
0.2.1 Added chaining example
0.2 Overhauled proposal, proposing new operator ?? instead of an extension to ?
0.1 Created

Votes

An option needs 2/3 votes to win

Approve Null Coalesce Operator RFC and merge patch into master? (91.2% approved)
User Vote
aharvey Yes
ajf Yes
amir Yes
auroraeosrose Yes
ben Yes
brianlmoon Yes
bwoebi Yes
daverandom Yes
derick Yes
dmitry No
duodraco Yes
fmk Yes
frozenfire Yes
guilhermeblanco Yes
gwynne Yes
hywan Yes
irker Yes
jedibc Yes
jpauli Yes
jwage Yes
kalle No
klaussilveira Yes
krakjoe Yes
leigh Yes
levim Yes
mfischer No
nikic Yes
philstu Yes
pollita Yes
ramsey Yes
rdohms Yes
reeze Yes
stas Yes
weierophinney Yes