# RFC: __toArray()

- Status: Inactive
- Authors: Steven Wade, stevenwadejr@gmail.com
- Date: 2019-08-28
- Version: 1.1
- Original: https://wiki.php.net/rfc/to-array
- Page: https://externals.io/rfc/to-array
- More for agents: search with https://externals.io/search.md?q={query} · RFCs at https://externals.io/rfc.md · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

## Discussions on the mailing list

- [Proposal for a RFC](https://externals.io/message/105589.md) — started on 2019-05-04, 33 messages
- [\[RFC - discussion\] __toArray()](https://externals.io/message/108369.md) — started on 2020-02-04, 19 messages

---

## 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](https://www.php.net/manual/en/language.oop5.magic.php) that give a class greater control over its interaction with the language. The methods [\_\_serialize() and \_\_unserialize()](https://externals.io/rfc/custom_object_serialization) 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:

```php
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:

```php
$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**

```php
function foo(array $person) {
    var_dump($person);
}
 
// Output
/*
array(2) {
  ["name"]=>
  string(8) "John Doe"
  ["email"]=>
  string(17) "j.doe@example.com"
}
*/
```

**Return Type**

```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"
}
*/
```

**array\_\* and built-in functions**

The array operating functions listed on the [Array Functions](https://www.php.net/manual/en/ref.array.php) would first convert an object implementing the \_\_toArray() method before continuing operations.

```php
print_r(
    array_keys($person)
);
 
// Output
/*
Array
(
    [0] => first
    [1] => email
)
*/
```

#### Strict Types

Automatic casting will not work when using strict types.

```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"
```

Manual casting within strict types will continue to work and is allowed.

```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
```

### 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](https://www.php.net/manual/en/class.arrayaccess.php) 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

![:?:](https://wiki.php.net/lib/images/smileys/question.svg) Help needed

### To Existing Extensions

![:?:](https://wiki.php.net/lib/images/smileys/question.svg) Help needed

### To Opcache

![:?:](https://wiki.php.net/lib/images/smileys/question.svg) Help needed

## Concerns

A [concern raised in the initial RFC proposal discussion](https://externals.io/message/105589#105594) 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](https://github.com/php/php-src/commit/eecd8961d94c50cc6cdc94ec80df8c1ce4881a76).

## Proposed Voting Choices

Vote will require 2/3 majority

## Patches and Tests

No patch exists yet. A [proof of concept](https://github.com/sgolemon/php-src/tree/experimental.toarray) for type casting was created by Sara Golemon, but no official patch has been created. Will need help with this.

## References

- PHP Manual: [magic methods](https://www.php.net/manual/en/language.oop5.magic.php), [Array Functions](https://www.php.net/manual/en/ref.array.php), [ArrayAccess](https://www.php.net/manual/en/class.arrayaccess.php) .
- PHP RFC: [New custom object serialization mechanism](https://externals.io/rfc/custom_object_serialization) .
- Initial idea and discussion: <https://externals.io/message/105589> .

## Rejected Features
