rfc:to-array

Differences

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

Link to this comparison view

Next revision
Previous revision
rfc:to-array [2019/08/29 04:05]
stevenwadejr created
rfc:to-array [2020/02/11 13:57] (current)
stevenwadejr Bump the version number now that it's under discussion and some feedback has been addressed
Line 1: Line 1:
 ====== PHP RFC: __toArray() ====== ====== PHP RFC: __toArray() ======
-  * Version: 0.1+  * Version: 1.1
   * Date: 2019-08-28   * Date: 2019-08-28
   * Author: Steven Wade, stevenwadejr@gmail.com   * Author: Steven Wade, stevenwadejr@gmail.com
-  * Status: Draft+  * Status: Under Discussion
   * First Published at: http://wiki.php.net/rfc/to-array   * First Published at: http://wiki.php.net/rfc/to-array
  
 ===== Introduction ===== ===== Introduction =====
-PHP contains many [[https://www.php.net/manual/en/language.oop5.magic.php|magic methods]] that give a class greater control over its interaction with the language. The methods [[https://wiki.php.net/rfc/custom_object_serialization|__serialize() and __unserialize()]] give a class control over how it is serialized, <nowiki>__clone()</nowiki> allows control over how self copies are made, and <nowiki>__toString()</nowiki> allows a class to control how it is represented when converted to a string.  
  
 This RFC proposes to add a new magic method called <nowiki>__toArray()</nowiki> to allow a class to control how it is represented when converted to an array. This RFC proposes to add a new magic method called <nowiki>__toArray()</nowiki> to allow a class to control how it is represented when converted to an array.
 +
 +PHP contains many [[https://www.php.net/manual/en/language.oop5.magic.php|magic methods]] that give a class greater control over its interaction with the language. The methods [[https://wiki.php.net/rfc/custom_object_serialization|__serialize() and __unserialize()]] give a class control over how it is serialized, <nowiki>__clone()</nowiki> allows control over how self copies are made, and <nowiki>__toString()</nowiki> allows a class to control how it is represented when converted to a string. Adding a <nowiki>__toArray()</nowiki> method gives developers the ability to transform a class to an array in similar fashion.
  
 ===== Proposal ===== ===== Proposal =====
Line 37: Line 38:
 } }
  
-$rfcAuthor = new Person('Steven Wade', 'stevenwadejr@gmail.com');+$person = new Person('John Doe', 'j.doe@example.com');
 </code> </code>
  
-Example default (current) behavior:+Example usage:
  
 <code php> <code php>
-print_r($rfcAuthor);+$personArray = (array$person// casting triggers __toArray() 
 +</code>
  
 +==== What this is ====
 +The example above shows the method <nowiki>__toArray()</nowiki> used in a type-casting context.  This proposal would have objects implementing the <nowiki>__toArray()</nowiki> magic method called within //any// array context including type hinting and return types (only when using weak typing - strong typing will throw an error).
 +
 +Similar to PHP's current implementation of <nowiki>__toString()</nowiki>, a copy of the given object's value as an array is made upon conversion.
 +
 +**Type Hinting**
 +
 +<code php>
 +function foo(array $person) {
 +    var_dump($person);
 +}
 +
 +// Output
 /* /*
-Person Object +array(2) { 
-+  ["name"]=> 
-    [name:protected] => Steven Wade +  string(8) "John Doe" 
-    [email:protected] => stevenwadejr@gmail.com +  ["email"]=> 
-    [foo] => bar +  string(17) "j.doe@example.com
-)+
 +*/ 
 +</code> 
 + 
 +**Return Type** 
 + 
 +<code php> 
 +function bar(Person $person): array { 
 +    return $person; 
 +
 + 
 +var_dump(bar($person)); 
 + 
 +// Output 
 +/* 
 +array(2) { 
 +  ["name"]=> 
 +  string(8"John Doe" 
 +  ["email"]=> 
 +  string(17) "j.doe@example.com" 
 +}
 */ */
 </code> </code>
  
 +**array_*  and built-in functions**
  
-Example with casting:+The array operating functions listed on the [[https://www.php.net/manual/en/ref.array.php|Array Functions]] would first convert an object implementing the <nowiki>__toArray()</nowiki> method before continuing operations.
  
 <code php> <code php>
-print_r((array) $rfcAuthor);+print_r( 
 +    array_keys($person) 
 +);
  
 +// Output
 /* /*
 Array Array
 ( (
-    [name] => Steven Wade +    [0] => first 
-    [email] => stevenwadejr@gmail.com+    [1] => email
 ) )
 */ */
 </code> </code>
  
 +=== Strict Types ===
 +
 +Automatic casting will not work when using strict types.
 +
 +<code php>
 +declare(strict_types=1);
 +
 +function bar(Person $person): array {
 +    return $person;
 +}
 +
 +bar($person); // Throws an error: "Return value of bar() must be of the type array, object returned"
 +
 +function foo(array $person) {
 +    var_dump($person);
 +}
 +
 +foo($person); // Throws an error: "Argument 1 passed to foo() must be of the type array, object given"
 +</code>
 +
 +Manual casting within strict types will continue to work and is allowed.
 +
 +<code php>
 +declare(strict_types=1);
 +
 +function bar(Person $person): array {
 +    return (array) $person;
 +}
 +
 +bar($person); // Returns an array
 +
 +function foo(array $person) {
 +    var_dump($person);
 +}
 +
 +foo((array) $person); // Allowed
 +</code>
 +
 +==== What this is not ====
 +This proposal does not allow accessing and setting values as you would in a normal array, that functionality remains with classes implementing the [[https://www.php.net/manual/en/class.arrayaccess.php|ArrayAccess]] interface.
 +
 +Array functions that operate on an array by reference such as <nowiki>sort</nowiki> or <nowiki>shuffle</nowiki> will not work on an object implementing <nowiki>__toArray()</nowiki> under this proposal.
  
 ===== Backward Incompatible Changes ===== ===== Backward Incompatible Changes =====
-What breaks, and what is the justification for it?+None
  
 ===== Proposed PHP Version(s) ===== ===== Proposed PHP Version(s) =====
Line 79: Line 160:
 ===== RFC Impact ===== ===== RFC Impact =====
 ==== To SAPIs ==== ==== To SAPIs ====
-Describe the impact to CLI, Development web server, embedded PHP etc.+:?: Help needed
  
 ==== To Existing Extensions ==== ==== To Existing Extensions ====
-Will existing extensions be affected?+:?: Help needed
  
 ==== To Opcache ==== ==== To Opcache ====
-It is necessary to develop RFC's with opcache in mind, since opcache is a core extension distributed with PHP.+:?: Help needed
  
-Please explain how you have verified your RFC's compatibility with opcache.+===== Concerns =====
  
-==== New Constants ==== +A [[https://externals.io/message/105589#105594|concern raised in the initial RFC proposal discussion]] referred to the existing behavior of casting and exposing object state:
-Describe any new constants so they can be accurately and comprehensively explained in the PHP documentation.+
  
-==== php.ini Defaults ==== +>As it currently stands, the array cast is the only operation capable of exposing object state without triggering any kind of access guardsit is very much required for anything that works with reflection and typed properties, and possibly the only operation in PHP that operates on state without some contraption intercepting its execution.
-If there are any php.ini settings then list: +
-  * hardcoded default values +
-  * php.ini-development values +
-  * php.ini-production values+
  
-===== Open Issues ===== +As a response to this concern, the new <nowiki>get_mangled_object_vars()</nowiki> function was added in [[https://github.com/php/php-src/commit/eecd8961d94c50cc6cdc94ec80df8c1ce4881a76|PHP 7.4]].
-Make sure there are no open issues when the vote starts! +
- +
-===== Unaffected PHP Functionality ===== +
-List existing areas/features of PHP that will not be changed by the RFC. +
- +
-This helps avoid any ambiguity, shows that you have thought deeply about the RFC's impact, and helps reduces mail list noise. +
- +
-===== Future Scope ===== +
-This section details areas where the feature might be improved in future, but that are not currently proposed in this RFC.+
  
 ===== Proposed Voting Choices ===== ===== Proposed Voting Choices =====
-Include these so readers know where you are heading and can discuss the proposed voting options.+Vote will require 2/3 majority
  
 ===== Patches and Tests ===== ===== Patches and Tests =====
-Links to any external patches and tests go here. +No patch exists yetA [[https://github.com/sgolemon/php-src/tree/experimental.toarray|proof of concept]] for type casting was created by Sara Golemonbut no official patch has been created Will need help with this.
- +
-If there is no patch, make it clear who will create a patch, or whether a volunteer to help with implementation is needed. +
- +
-Make it clear if the patch is intended to be the final patch, or is just a prototype. +
- +
-For changes affecting the core languageyou should also provide a patch for the language specification. +
- +
-===== Implementation ===== +
-After the project is implemented, this section should contain  +
-  - the version(s) it was merged into +
-  - a link to the git commit(s) +
-  - a link to the PHP manual entry for the feature +
-  - a link to the language specification section (if any)+
  
 ===== References ===== ===== References =====
-Links to external referencesdiscussions or RFCs+  * PHP Manual: [[https://www.php.net/manual/en/language.oop5.magic.php|magic methods]][[https://www.php.net/manual/en/ref.array.php|Array Functions]], [[https://www.php.net/manual/en/class.arrayaccess.php|ArrayAccess]] .  
 +  * PHP RFC: [[https://wiki.php.net/rfc/custom_object_serialization|New custom object serialization mechanism]] .  
 +  * Initial idea and discussion: [[https://externals.io/message/105589]] . 
  
 ===== Rejected Features ===== ===== Rejected Features =====
-Keep this updated with features that were discussed on the mail lists.+
rfc/to-array.1567051534.txt.gz · Last modified: 2019/08/29 04:05 by stevenwadejr