rfc:convert_numeric_keys_in_object_array_casts

Differences

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

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
rfc:convert_numeric_keys_in_object_array_casts [2016/11/14 17:41]
ajf vote closed
rfc:convert_numeric_keys_in_object_array_casts [2017/11/30 14:50] (current)
ajf
Line 3: Line 3:
   * Date: 2016-10-21   * Date: 2016-10-21
   * Author: Andrea Faulds, ajf@ajf.me   * Author: Andrea Faulds, ajf@ajf.me
-  * Status: Accepted (PHP 7.2)+  * Status: Implemented (PHP 7.2)
   * First Published at: http://wiki.php.net/rfc/convert_numeric_keys_in_object_array_casts   * First Published at: http://wiki.php.net/rfc/convert_numeric_keys_in_object_array_casts
  
Line 10: Line 10:
 The PHP language has two core data types which are collections of key/value pairs. The PHP language has two core data types which are collections of key/value pairs.
  
-The first of these, the //array//, is an ordered map of integer or string keys to arbitrary values. There is no overlap between integer and string keys in arrays; if a string fits the format ''/^0|([1-9][0-9]*)$/'' and is small enough (<php>PHP_INT_MIN</php> ≤ n ≤ <php>PHP_INT_MAX</php>), it is converted to an integer key. Such strings are termed //numeric strings//.+The first of these, the //array//, is an ordered map of integer or string keys to arbitrary values. There is no overlap between integer and string keys in arrays; if a string fits the format ''/^(0|(-?[1-9][0-9]*))$/'' and is small enough (<php>PHP_INT_MIN</php> ≤ n ≤ <php>PHP_INT_MAX</php>), it is converted to an integer key. Such strings are termed //numeric strings//.
  
 The second of these, the //object//, is an ordered map of string property names to arbitrary values. Integer property names are not permitted, these are converted to string property names. Objects have some other attributes, but they do not concern us here. The second of these, the //object//, is an ordered map of string property names to arbitrary values. Integer property names are not permitted, these are converted to string property names. Objects have some other attributes, but they do not concern us here.
Line 24: Line 24:
 Various edge cases in the Zend Engine exist where array HashTables can contain numeric string keys, and object HashTables can contain integer keys. In such cases, these keys are inaccessible from PHP code, because the code handling arrays will never look for numeric string keys in the HashTable (as arrays map those to integer keys), and the code handling objects will never look for integer keys in the HashTable (as objects map those to string keys). Various edge cases in the Zend Engine exist where array HashTables can contain numeric string keys, and object HashTables can contain integer keys. In such cases, these keys are inaccessible from PHP code, because the code handling arrays will never look for numeric string keys in the HashTable (as arrays map those to integer keys), and the code handling objects will never look for integer keys in the HashTable (as objects map those to string keys).
  
-This RFC focuses on a specific edge case, that of object-to-array casts and array-to-object casts. Currently, when using <php>(object)</php> or <php>settype()</php> to convert an object to an array, or when using <php>(array)</php> or <php>settype()</php> to convert an array to an object, the inner HashTable is naïvely copied or referenced without its keys being changed to reflect the restrictions on array keys and object property names, leading to inaccessible array keys or object properties in some cases. For example, <php>$arr = [0 => 1, 1 => 2, 2 => 3]; $obj = (object)$arr;</php> produces an object with inaccessible properties named <php>0</php>, <php>1</php> and <php>2</php>, while <php>$obj = new stdClass; $obj->{'0'} = 1; $obj->{'1'} = 2; $obj->{'2'} = 3;</php> produces an array with the inaccessible keys <php>"0"</php>, <php>"1"</php> and <php>"2"</php>. The same issue also occurs when using <php>get_object_vars()</php>.+This RFC focuses on a specific edge case, that of object-to-array casts and array-to-object casts. Currently, when using <php>(object)</php> or <php>settype()</php> to convert an object to an array, or when using <php>(array)</php> or <php>settype()</php> to convert an array to an object, the inner HashTable is naïvely copied or referenced without its keys being changed to reflect the restrictions on array keys and object property names, leading to inaccessible array keys or object properties in some cases. For example, <php>$arr = [0 => 1, 1 => 2, 2 => 3]; $obj = (object)$arr;</php> produces an object with inaccessible properties named <php> 0</php>, <php>1</php> and <php>2</php>, while <php>$obj = new stdClass; $obj->{'0'} = 1; $obj->{'1'} = 2; $obj->{'2'} = 3; $arr = (array)$obj;</php> produces an array with the inaccessible keys <php>"0"</php>, <php>"1"</php> and <php>"2"</php>. The same issue also occurs when using <php>get_object_vars()</php>.
  
 ===== Proposal ===== ===== Proposal =====
Line 30: Line 30:
 ==== High-level ==== ==== High-level ====
  
-This RFC proposes to fix this issue for object-to-array casts and array-to-object casts, both for the casting operators and for <php>settype()</php>, and also fix the same issue in <php>get_object_vars()</php>. This would be done by converting the keys of array or object HashTables as appropriate, so numeric string property names in objects would be converted to integer array keys, and vice-versa. Therefore, there would be no inaccessible properties. For example, <php>$arr = [0 => 1, 1 => 2, 2 => 3]; $obj = (object)$arr;</php> would now produce an object with accessible properties named <php>"0"</php>, <php>"1"</php> and <php>"2"</php>, and <php>$obj = new stdClass; $obj->{'0'} = 1; $obj->{'1'} = 2; $obj->{'2'} = 3;</php> would now produce an array with the accessible keys <php>0</php>, <php>1</php> and <php>2</php>.+This RFC proposes to fix this issue for object-to-array casts and array-to-object casts, both for the casting operators and for <php>settype()</php>, and also fix the same issue in <php>get_object_vars()</php>. This would be done by converting the keys of array or object HashTables as appropriate, so numeric string property names in objects would be converted to integer array keys, and vice-versa. Therefore, there would be no inaccessible properties. For example, <php>$arr = [0 => 1, 1 => 2, 2 => 3]; $obj = (object)$arr;</php> would now produce an object with accessible properties named <php>"0"</php>, <php>"1"</php> and <php>"2"</php>, and <php>$obj = new stdClass; $obj->{'0'} = 1; $obj->{'1'} = 2; $obj->{'2'} = 3; $arr = (array)$obj;</php> would now produce an array with the accessible keys <php> 0</php>, <php>1</php> and <php>2</php>.
  
 ==== Internals ==== ==== Internals ====
Line 96: Line 96:
 ===== Patches and Tests ===== ===== Patches and Tests =====
  
-The pull request is here: https://github.com/php/php-src/pull/2142+The pull request for the PHP interpreter is here: https://github.com/php/php-src/pull/2142 
 + 
 +There is no language specification patch, because none is required. The language specification did not specify or comment on this bug.
  
 ===== Implementation ===== ===== Implementation =====
 +
 +This is implemented in master, which will become PHP 7.2. The commit is: https://github.com/php/php-src/commit/a0502b89a65d24eb191a7c85bcffcf9b91454735
 +
 After the project is implemented, this section should contain  After the project is implemented, this section should contain 
-  - the version(s) it was merged to 
-  - a link to the git commit(s) 
   - a link to the PHP manual entry for the feature   - a link to the PHP manual entry for the feature
  
rfc/convert_numeric_keys_in_object_array_casts.1479145317.txt.gz · Last modified: 2017/09/22 13:28 (external edit)