# Casting array to any class

- Thread: https://externals.io/message/118821
- Original archive: https://news-web.php.net/php.internals/118821
- Started by Gianni Gentile on 2022-10-15T11:18:29+00:00
- Messages: 3
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #118821 — Gianni Gentile — 2022-10-15T11:18:29+00:00

URL: https://externals.io/message/118821#118821

Hi,

in my every day experience, using custom DTO classes and different API, 
I often write code to instantiate my objects from associative arrays.

What are your thoughts on introduce the `(AnyType)` cast to instantiate 
objects from associative array (or object properties also)?

In my proposal, if AnyType implements __set_state(), casting should be 
syntactic sugar for:

     AnyType::_set_state((array) $data)

just for (useless) example, consider DateTime or DateTimeImmutable (both 
have __set_state() implementation); when applied to objects of that 
type, we can write:

     $dt = new DateTime();

     $dtArray = (array) $dt; // 3 elements array

     $copyOfDt = (DateTime) $dtArray; // or simply $copyOfDt = 
(DateTime) $dt;

In case AnyType does not implements __set_state(), casting should create 
a new instance, assigning values to properties, taken from array values 
with corresponding key (in a similar way class objects are created when 
row is fetched from database specifying PDO_FETCH_CLASS) eventually 
invoking __set() magic method for properties not declared;

In this scenario,

     (object) ['one' => 1, 'two' => 2]

and

     (StdClass) ['one' => 1, 'two' => 2]

do exactly the same work.


Reasons:

- clear code

- array to object conversion (casting) would be the simmetrical 
counterpart of object to array conversion


Thanks,

Gianni

-- 

To unsubscribe, visit: https://www.php.net/unsub.php

---

## #118823 — Thomas Nunninger — 2022-10-15T14:12:35+00:00

URL: https://externals.io/message/118821#118823 · In reply to: #118821

Hi,

Am 15.10.22 um 13:18 schrieb Gianni Gentile:
> Hi,
> 
> in my every day experience, using custom DTO classes and different API, 
> I often write code to instantiate my objects from associative arrays.
> 
> What are your thoughts on introduce the `(AnyType)` cast to instantiate 
> objects from associative array (or object properties also)?
> 
> In my proposal, if AnyType implements __set_state(), casting should be 
> syntactic sugar for:
> 
>      AnyType::_set_state((array) $data)
> 
> just for (useless) example, consider DateTime or DateTimeImmutable (both 
> have __set_state() implementation); when applied to objects of that 
> type, we can write:
> 
>      $dt = new DateTime();
> 
>      $dtArray = (array) $dt; // 3 elements array
> 
>      $copyOfDt = (DateTime) $dtArray; // or simply $copyOfDt = 
> (DateTime) $dt;
> 
> In case AnyType does not implements __set_state(), casting should create 
> a new instance, assigning values to properties, taken from array values 
> with corresponding key (in a similar way class objects are created when 
> row is fetched from database specifying PDO_FETCH_CLASS) eventually 
> invoking __set() magic method for properties not declared;
> 
> In this scenario,
> 
>      (object) ['one' => 1, 'two' => 2]
> 
> and
> 
>      (StdClass) ['one' => 1, 'two' => 2]
> 
> do exactly the same work.
> 
> 
> Reasons:
> 
> - clear code
> 
> - array to object conversion (casting) would be the simmetrical 
> counterpart of object to array conversion


I see your use case and I often have similar needs. Some thoughts:

* Are there any restrictions regarding the matching of array keys and 
the class attributes? What if there are additional keys in the array 
that do not have corresponding attributes? What if there are some 
attributes in the class that do not exist in the array?

* Can I forbid a class to be created by casting from an array? When I 
think about domain entities/aggregates, such a casting would allow to 
create an invalid state of the object without any checks. (Okay, we have 
similar issues when recreating them from a database via some ORM.)

BTW:

<?php declare(strict_types=1);

class A
{
     private string $myPrivate = 'private';
     protected string $myProtected = 'protected';
     public string $myPublic = 'public';
}

$a = new A();

var_dump((array) $a);

?>

Will dump with modified array keys:

/home/thomas/test.php:12:
array(3) {
   '\0A\0myPrivate' =>
   string(7) "private"
   '\0*\0myProtected' =>
   string(9) "protected"
   'myPublic' =>
   string(6) "public"
}

So it's not as symmetric as intended.

Regards
Thomas

---

## #118826 — Larry Garfield — 2022-10-15T14:33:15+00:00

URL: https://externals.io/message/118821#118826 · In reply to: #118821

> Hi,
>
> in my every day experience, using custom DTO classes and different API, 
> I often write code to instantiate my objects from associative arrays.
>
> What are your thoughts on introduce the `(AnyType)` cast to instantiate 
> objects from associative array (or object properties also)?
>
> In my proposal, if AnyType implements __set_state(), casting should be 
> syntactic sugar for:
>
>      AnyType::_set_state((array) $data)
>
> just for (useless) example, consider DateTime or DateTimeImmutable (both 
> have __set_state() implementation); when applied to objects of that 
> type, we can write:
>
>      $dt = new DateTime();
>
>      $dtArray = (array) $dt; // 3 elements array
>
>      $copyOfDt = (DateTime) $dtArray; // or simply $copyOfDt = 
> (DateTime) $dt;
>
> In case AnyType does not implements __set_state(), casting should create 
> a new instance, assigning values to properties, taken from array values 
> with corresponding key (in a similar way class objects are created when 
> row is fetched from database specifying PDO_FETCH_CLASS) eventually 
> invoking __set() magic method for properties not declared;
>
> In this scenario,
>
>      (object) ['one' => 1, 'two' => 2]
>
> and
>
>      (StdClass) ['one' => 1, 'two' => 2]
>
> do exactly the same work.
>
>
> Reasons:
>
> - clear code
>
> - array to object conversion (casting) would be the simmetrical 
> counterpart of object to array conversion

Most DTOs have a 1:1 match from constructor to properties.  In current PHP versions, that means they often look like this:

class Point
{
    public function __construct(
        public readonly int $x,
        public readonly int $y,
        public readonly int $z,
    ) {}
}

Which means, in current PHP versions, you can use named args and splat to create one from an array.

$data = ['x' => 1, 'y' => 2, 'z' => 3];

$point = new Point(...$data);

No casting necessary.

True, that's not true of all such classes, but certainly the plurality.  In the cases where it's not, an explicit named constructor (via a Trait or otherwise) is a more self-documenting approach.

--Larry Garfield
