PHP RFC: __toArray()
- Version: 1.1
- Date: 2019-08-28
- Author: Steven Wade, stevenwadejr@gmail.com
- Status: Under Discussion
- First Published at: http://wiki.php.net/rfc/to-array
Introduction
This RFC proposes to add a new magic method called __toArray() to allow a class to control how it is represented when converted to an array.
PHP contains many magic methods that give a class greater control over its interaction with the language. The methods __serialize() and __unserialize() give a class control over how it is serialized, __clone() allows control over how self copies are made, and __toString() allows a class to control how it is represented when converted to a string. Adding a __toArray() method gives developers the ability to transform a class to an array in similar fashion.
Proposal
Example:
class Person { protected $name; protected $email; public $foo = 'bar'; public function __construct(string $name, string $email) { $this->name = $name; $this->email = $email; } public function __toArray() { return [ 'name' => $this->name, 'email' => $this->email, ]; } } $person = new Person('John Doe', 'j.doe@example.com');
Example usage:
$personArray = (array) $person; // casting triggers __toArray()
What this is
The example above shows the method __toArray() used in a type-casting context. This proposal would have objects implementing the __toArray() 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 __toString(), a copy of the given object's value as an array is made upon conversion.
Type Hinting
function foo(array $person) { var_dump($person); } // Output /* array(2) { ["name"]=> string(8) "John Doe" ["email"]=> string(17) "j.doe@example.com" } */
Return Type
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" } */
array_* and built-in functions
The array operating functions listed on the Array Functions would first convert an object implementing the __toArray() method before continuing operations.
print_r( array_keys($person) ); // Output /* Array ( [0] => first [1] => email ) */
Strict Types
Automatic casting will not work when using strict types.
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"
Manual casting within strict types will continue to work and is allowed.
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
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 ArrayAccess interface.
Array functions that operate on an array by reference such as sort or shuffle will not work on an object implementing __toArray() under this proposal.
Backward Incompatible Changes
None
Proposed PHP Version(s)
Next PHP version (target 8.0)
RFC Impact
To SAPIs
Help needed
To Existing Extensions
Help needed
To Opcache
Help needed
Concerns
A concern raised in the initial RFC proposal discussion referred to the existing behavior of casting and exposing object state:
As it currently stands, the array cast is the only operation capable of exposing object state without triggering any kind of access guards: it 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.
As a response to this concern, the new get_mangled_object_vars() function was added in PHP 7.4.
Proposed Voting Choices
Vote will require 2/3 majority
Patches and Tests
No patch exists yet. A proof of concept for type casting was created by Sara Golemon, but no official patch has been created. Will need help with this.
References
- PHP RFC: New custom object serialization mechanism .
- Initial idea and discussion: https://externals.io/message/105589 .