rfc:isset_ternary

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
rfc:isset_ternary [2014/09/09 01:15] – ` to '' ajfrfc:isset_ternary [2017/09/22 13:28] (current) – external edit 127.0.0.1
Line 1: Line 1:
-====== PHP RFC: Implicit isset() in Shorthand Ternary Operator ====== +====== PHP RFC: Null Coalesce Operator ====== 
-  * Version: 0.1 +  * Version: 0.2.3 
-  * Date: 2014-09-06 +  * Date: 2014-09-06, last updated 2014-09-16 
-  * Author: Andrea Fauldsajf@ajf.me +  * Author: Andrea Faulds <ajf@ajf.me
-  * Status: Under Discussion+  * Contributor: Nikita Popov <nikic@php.net> (initial patch) 
 +  * Status: Implemented (PHP 7)
   * First Published at: http://wiki.php.net/rfc/isset_ternary   * First Published at: http://wiki.php.net/rfc/isset_ternary
  
Line 9: Line 10:
 ===== Introduction ===== ===== 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).+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 ''<nowiki>isset($_GET['mykey']) ? $_GET['mykey'] : ""</nowiki>'', is unnecessarily cumbersome. The short ternary operator, ''?:'' provides a way to do this much more conveniently: ''<nowiki>$_GET['mykey'] ?""</nowiki>''. 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 ===== ===== Proposal =====
  
-The ''?:'' operator is overloadedsuch that if the first operand can be used with ''isset''an implicit ''isset'' is performed alongside the truthiness check. This means the ''$_GET['mykey'] ?""'' shorthand is completely safe and will not raise an E_NOTICE.+The coalesce, or ''??''operator is addedwhich returns the result of its first operand if it exists and is not NULLor else its second operand. This means the ''<nowiki>$_GET['mykey'] ?""</nowiki>'' is completely safe and will not raise an E_NOTICE. Some examples of its use:
  
-Internally this is actually implemented by rewriting the expression within the compiler from ''$a ?: $b'' to ''empty($a) ? $b : $a'' if ''$a'' would work with ''isset''. This avoids introducing any new opcodes and allows us to leverage the existing infrastructure in place for ''empty''.+<code php> 
 +// Fetches the request parameter user and results in 'nobodyif it doesn't exist 
 +$username = $_GET['user'] ?? 'nobody'
 +// equivalent to: $username = isset($_GET['user']) ? $_GET['user'] : 'nobody';
  
-==== Backwards-compatibility considerations ====+// 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; }
  
-Because ''empty'' is used, which performs a falsiness check, existing code using the ''?:'' operator should function the same. However, now no ''E_NOTICE'' will be raised if the variable does not exist. While this should not affect most applications, it might affect some applications using custom error handlers, so this is a minor backwards-compatibility break and targets a major version.+// 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; 
 +</code>
  
-===== Proposed PHP Version(s) =====+It can even be chained:
  
-This proposed for the next PHP x, which at the time of this writing would be PHP 7.+<code php> 
 +$= NULL; 
 +$y = NULL; 
 +$z = 3; 
 +var_dump($x ?? $y ?? $z); // int(3)
  
-===== Open Issues =====+$x ["yarr" => "meaningful_value"]; 
 +var_dump($x["aharr"] ?? $x["waharr"] ?? $x["yarr"]); // string(16) "meaningful_value" 
 +</code>
  
-None I'm aware of.+This example demonstrates the precedence relative to the ternary operator and the boolean or operator, which is the same as C#:
  
-===== Unaffected PHP Functionality =====+<code 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) 
 +</code>
  
-The behaviour of the long-form ternary operator, ''$a ? $b $c'', ''isset'' and ''empty'' are unaffected. Where the expression is not compatible with ''isset'', the existing behaviour continues to be used.+This example demonstrates how it is a short-circuiting operator:
  
-===== Future Scope =====+<code php> 
 +function foo() { 
 +    echo "executed!", PHP_EOL; 
 +
 +var_dump(true ?? foo()); // outputs bool(true), "executed!" does not appear as it short-circuited 
 +</code>
  
-None I can think of currently.+===== Proposed PHP Version(s) =====
  
-===== Proposed Voting Choices ===== +This proposed for the next PHP xwhich at the time of this writing would be PHP 7.
- +
-As this is a language changea 2/3 majority is required. A straight Yes/No vote would be held.+
  
 ===== Patches and Tests ===== ===== Patches and Tests =====
  
-A pull request with a working implementation and test, targeting master, is here: https://github.com/php/php-src/pull/809+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. 
 + 
 +<doodle title="Approve Null Coalesce Operator RFC and merge patch into master?" auth="ajf" voteType="single" closed="true"> 
 +   * Yes 
 +   * No 
 +</doodle>
  
 ===== Implementation ===== ===== Implementation =====
-After the project is implemented, this section should contain  + 
-  - the version(sit was merged to +Merged into master (which will be PHP 7): https://github.com/php/php-src/commit/2d069f640e6cccfa3ba8b1e4f375ade20fb33f64 
-  a link to the git commit(s) + 
-  - a link to the PHP manual entry for the feature+Documented at: http://php.net/manual/en/language.operators.comparison.php
  
 ===== References ===== ===== References =====
Line 65: Line 100:
  
 This list is quite probably incomplete. This list is quite probably incomplete.
 +
 +Operator precedence in C#: http://msdn.microsoft.com/en-us/library/6a71f45d.aspx
  
 ===== Rejected Features ===== ===== Rejected Features =====
 Keep this updated with features that were discussed on the mail lists. Keep this updated with features that were discussed on the mail lists.
 +
 +===== Errata =====
 +
 +The name of this RFC [[http://blog.ajf.me/2015-12-07-poorly-named-rfcs|ought to have been "null coalescing operator", not "null coalesce operator"]].
 +
 +===== 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
rfc/isset_ternary.1410225328.txt.gz · Last modified: 2017/09/22 13:28 (external edit)