# RFC: Null Coalesce Operator

- Status: Implemented (PHP 7.0)
- Authors: Andrea Faulds ajf@ajf.me
- Date: 2014-09-06, last updated 2014-09-16
- Version: 0.2.3
- Original: https://wiki.php.net/rfc/isset_ternary
- Page: https://externals.io/rfc/isset_ternary
- More for agents: search with https://externals.io/search.md?q={query} · RFCs at https://externals.io/rfc.md · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

## Votes

### Approve Null Coalesce Operator RFC and merge patch into master? (closed)

Yes: 31 · No: 3

Voters: 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)

## Discussions on the mailing list

- [\[RFC\] Implicit isset() in Shorthand Ternary Operator](https://externals.io/message/77083.md) — started on 2014-09-06, 34 messages
- [\[RFC\] Implicit isset() in Shorthand Ternary Operator](https://externals.io/message/77272.md) — started on 2014-09-16, 3 messages
- [\[VOTE\]\[RFC\] Null Coalesce Operator](https://externals.io/message/77356.md) — started on 2014-09-19, 6 messages
- [Question on Null Coalesce Operator ( ?? )](https://externals.io/message/79583.md) — started on 2014-12-11, 2 messages
- [Fix incorrect ternary '?' associativity for 7.0?](https://externals.io/message/79623.md) — started on 2014-12-13, 28 messages

---

## 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:

```php
// 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:

```php
$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#:

```php
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:

```php
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.

## Vote

As this is a language change, a 2/3 majority is required. A straight Yes/No vote is being held.

Voting started on 2014-09-20 and ended on 2014-09-27.

**Vote: Approve Null Coalesce Operator RFC and merge patch into master?** — Yes: 31 · No: 3 (closed)

## Implementation

Merged into master (which will be PHP 7): <https://github.com/php/php-src/commit/2d069f640e6cccfa3ba8b1e4f375ade20fb33f64>

Documented at: <http://php.net/manual/en/language.operators.comparison.php>

## References

There have been several previous discussions and proposals about adding an ifsetor operator with similar behaviour, or changing the behaviour of `?:`, indeed there has been at least one each year:

- 2004: [http://marc.info/?t=108214447100002&amp;r=1&amp;w=2](http://marc.info/?t=108214447100002&r=1&w=2) and [http://marc.info/?t=108214551500002&amp;r=1&amp;w=2](http://marc.info/?t=108214551500002&r=1&w=2)
- 2005: [http://marc.info/?t=111826997700001&amp;r=1&amp;w=2](http://marc.info/?t=111826997700001&r=1&w=2), [http://marc.info/?t=111829868900001&amp;r=1&amp;w=2](http://marc.info/?t=111829868900001&r=1&w=2) and [http://marc.info/?t=113069916200003&amp;r=1&amp;w=2](http://marc.info/?t=113069916200003&r=1&w=2)
- 2006: [http://marc.info/?t=114669117400001&amp;r=1&amp;w=2](http://marc.info/?t=114669117400001&r=1&w=2)
- 2007: [http://marc.info/?l=php-internals&amp;m=118208519027980&amp;w=2](http://marc.info/?l=php-internals&m=118208519027980&w=2)
- 2008: [RFC: ifsetor()](https://externals.io/rfc/ifsetor) - [http://marc.info/?t=120136702900003&amp;r=1&amp;w=2](http://marc.info/?t=120136702900003&r=1&w=2)
- 2009: [http://marc.info/?l=php-internals&amp;m=124214617109310&amp;w=2](http://marc.info/?l=php-internals&m=124214617109310&w=2)
- 2011: [http://marc.info/?l=php-internals&amp;m=130158916712977&amp;w=2](http://marc.info/?l=php-internals&m=130158916712977&w=2)
- 2013: [http://marc.info/?t=138547713500001&amp;r=1&amp;w=2](http://marc.info/?t=138547713500001&r=1&w=2)

This list is quite probably incomplete.

Operator precedence in C#: <http://msdn.microsoft.com/en-us/library/6a71f45d.aspx>

## Rejected Features

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

## Errata

The name of this RFC [ought to have been "null coalescing operator", not "null coalesce operator"](http://blog.ajf.me/2015-12-07-poorly-named-rfcs).

## Changelog

- (2016-03-13) Added Errata
- v0.2.3 - Added short-circuit example
- v0.2.2 - Added precedence example
- v0.2.1 - Added chaining example
- v0.2 - Overhauled proposal, proposing new operator `??` instead of an extension to `?:`
- v0.1 - Created
