This is an old revision of the document!
PHP RFC: Null Coalesce Operator
- Version: 0.2.3
- Date: 2014-09-06, last updated 2014-09-16
- Author: Andrea Faulds ajf@ajf.me
- Contributor: Nikita Popov nikic@php.net (initial patch)
- Status: Implemented (PHP 7)
- First Published at: http://wiki.php.net/rfc/isset_ternary
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 practise, 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.
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.
Implementation
Merged into master (which will be PHP 7): https://github.com/php/php-src/commit/2d069f640e6cccfa3ba8b1e4f375ade20fb33f64
Not yet documented.
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:
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.
Changelog
- 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