rfc:in_operator

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:in_operator [2015/02/19 23:56] – updated draft kelunikrfc:in_operator [2017/09/22 13:28] (current) – external edit 127.0.0.1
Line 1: Line 1:
 ====== PHP RFC: In Operator ====== ====== PHP RFC: In Operator ======
-  * Version: 0.2 +  * Version: 0.5.1 
-  * Date: 2015-02-20+  * Date: 2015-03-15
   * Authors: Niklas Keller <me@kelunik.com>, Bob Weinand <bobwei9@hotmail.com>   * Authors: Niklas Keller <me@kelunik.com>, Bob Weinand <bobwei9@hotmail.com>
-  * Status: Draft+  * Status: Declined
   * First Published at: http://wiki.php.net/rfc/in_operator   * First Published at: http://wiki.php.net/rfc/in_operator
  
 ===== Introduction ===== ===== Introduction =====
-This RFC adds a new ''in'' operator which simplifies ''contains'' checks for strings and arrays. Currently, we have to use ''in_array($needle, $haystack, true)'' or ''strpos($haystack, $needle) !== false''. These functions have a inconsistent parameter order, so it's hard to remember which is the right one for each. The ''in'' operator makes these checks way more readable.+This RFC adds a new ''in'' operator which simplifies ''contains'' checks for strings and arrays. The ''in'' operator makes these checks way more readable and lowers the cognitive load. Additionally, it also works for ''Traversable''
 + 
 +===== Motivation ===== 
 +Checking if a specific input in an allowed range of value is a very common check in web application, therefore this operator simplifies those checks (and besides makes them a little bit faster). Currently, we have to use ''in_array($needle, $haystack, true)'' or ''strpos($haystack, $needle) !== false''. These functions have a inconsistent parameter order, so it's hard to remember which is the right one for each. Additionally, omitting the third parameter for ''in_array'' is very common which led to security vulnerabilities in the past.
  
 ===== Proposal ===== ===== Proposal =====
 Add a new operator ''(expr1) in (expr2)''. It checks whether ''expr2'' contains ''expr1''. Add a new operator ''(expr1) in (expr2)''. It checks whether ''expr2'' contains ''expr1''.
  
-It uses strict comparison (''==='') for array values and doesn't search recursively.+It uses strict comparison (''==='') for array values / instances of ''Traversable'' and doesn't search recursively.
  
 <code php> <code php>
Line 20: Line 23:
 $contains = "0e0" in ["0"]; // false, because of strict comparison $contains = "0e0" in ["0"]; // false, because of strict comparison
 $contains = 0 in ["0"]; // false, because of strict comparison $contains = 0 in ["0"]; // false, because of strict comparison
 +
 +$contains = ["foo"] in [["foo"], ["bar"]]; // true
 +$contains = ["foo"] in ["foo"]; // false
 </code> </code>
  
-If the first parameter is an array, it checks for every element whether it's contained in the ''$haystack'' or notThis is an advantage compared to ''in_array''. It doesn't check the values in ''$needle'' recursively, so it's still possible to check if an array contains another array, but makes checking multiple scalars easier:+''Traversable''s are only iterated until there's a match.
  
 <code php> <code php>
-$contains = ["foo""bar"] in ["foo", "baz", "bar"]; // true +function gen () { 
-$contains = ["foo", "bar", "baz"] in ["foo", "bar"]; // false +    yield "foo"
-$contains = [["foo", "bar"]] in [["foo", "bar"], ["foo", "baz"]]; // true +    yield "bar"; 
-$contains = [["foo", "bar"]] in ["foo", "bar"]; // false+    // code below here wouldn't be executed if "bar" matches 
 +    // because it stops if there's a match. 
 +
 + 
 +$contains = "bar" in gen(); // true 
 +$contains = "baz" in gen(); // false
 </code> </code>
  
-For stings, it behaves exactly like ''strpos($haystack, $needle) !== false'':+If ''$haystack'' is a stringit's a simple ''contains'' check. 
 <code php> <code php>
 $contains = "foo" in "foobar"; // true $contains = "foo" in "foobar"; // true
Line 37: Line 49:
 </code> </code>
  
-Objects are not supported, because we already have ''isset'' here.+Other expressions than ''mixed in array|Traversable'' or ''string in string'' throw an ''EngineException''
 + 
 +==== Why strict? ==== 
 +It's strict because otherwise something like ''"foo" in [0]'' would pass. 
 + 
 +==== Precedence ==== 
 +It should have the same precedence as ''instanceof'', so it's possible to negate it: 
 + 
 +<code php> 
 +if (!$input in $validValues) { 
 +    // ... 
 +
 +</code>
  
 ===== Backward Incompatible Changes ===== ===== Backward Incompatible Changes =====
-New reserved keyword ''in''. This affects function, class and method names.+New reserved keyword ''in''. This affects function, constant and class, **but not** class constant and method names, because it depends on the context sensitive lexer being merged.
  
 ===== Proposed PHP Version(s) ===== ===== Proposed PHP Version(s) =====
Line 48: Line 72:
 ==== New Constants ==== ==== New Constants ====
 A ''T_IN'' constant for use with ext/tokenizer has been added. A ''T_IN'' constant for use with ext/tokenizer has been added.
- 
-===== Open Issues ===== 
-Make sure there are no open issues when the vote starts! 
  
 ===== Future Scope ===== ===== Future Scope =====
-None.+There could be a syntax that allows to check for multiple values at once, e.g. 
 +<code php> 
 +$contains = ...["foo", "bar"] in ["foo", "baz", "bar"]; 
 +</code>
  
-===== Proposed Voting Choices ===== +===== Votes ===== 
-Requires a 2/3 majority, simple yes no vote.+Requires a 2/3 majority. Even if it passesit will //only// get merged if the [[rfc/context_sensitive_lexer|context sensitive lexer]] gets merged.
  
-===== Patches and Tests ===== +<doodle title="Introduce the in operator?" auth="kelunik" voteType="single" closed="true"> 
-TBD+   * Yes 
 +   * No 
 +</doodle>
  
-===== Implementation ===== +Voting started on 2015-03-15 and ends on 2015-03-29. 
-TBD+ 
 +===== Patches and Tests ===== 
 +  * https://github.com/php/php-src/pull/1121
  
 ===== 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.
 +
 +===== Changelog =====
 +  * v0.5: Removed integer support, so the strictness is consistent.
 +  * v0.4: Removed possibility to check multiple values using an array.
rfc/in_operator.1424390192.txt.gz · Last modified: 2017/09/22 13:28 (external edit)