TheDragonCode / simple-data-transfer-object

Simple Data Transfer Objects
MIT License
8 stars 2 forks source link

Bug Fix Readonly Proporty #45

Closed akbarali1 closed 6 months ago

akbarali1 commented 6 months ago
<?php

namespace App\DTO;

use DragonCode\SimpleDataTransferObject\DataTransferObject;

class YourInstance extends DataTransferObject
{
    public readonly string $foo;

    public $bar;

    public $baz;

    public $qwerty;
}
$instance = YourInstance::make([
    'foo' => 'Foo',
    'bar' => 'Bar',
    'baz' => 'Baz',
]);

Error: Cannot initialize readonly property App\DTO\YourInstance::$foo from scope DragonCode\SimpleDataTransferObject\DataTransferObject

andrey-helldar commented 6 months ago

Yes, because php itself prohibits assigning readonly values to properties outside the constructor. That's why it's called readonly.

https://php.watch/versions/8.1/readonly

akbarali1 commented 6 months ago

Yes, because php itself prohibits assigning readonly values to properties outside the constructor. That's why it's called readonly.

https://php.watch/versions/8.1/readonly

You are wrong, it is possible. I did it myself in DTO.

https://github.com/akbarali1/data-object?tab=readme-ov-file#20-version-supported-readonly-properties

akbarali1 commented 6 months ago

It can be done

andrey-helldar commented 6 months ago

It works

class Some
{
    public function __construct(
        public readonly string $foo
    ) {
    }
}

die((new Some('foo'))->foo);
class Some
{
    public readonly string $foo;

    public function __construct(
        string $foo
    ) {
        $this->foo = $foo;
    }
}

die((new Some('foo'))->foo);
class Some
{
    public readonly string $foo;

    public function __construct(
        string $foo
    ) {
        $key = 'foo';

        $this->$key = $foo;
    }
}

die((new Some('foo'))->foo);

It's doesn't works

abstract class BaseClass
{
    public function __construct(
        string $foo
    ) {
        $this->foo = $foo;
    }
}

class Some extends BaseClass
{
    public readonly string $foo;
}

die((new Some('foo'))->foo);

To make this work, we need to move the mechanics of processing incoming data into the __construct method of the final class. But in this case the question arises - why a DTO package when it will be in the application anyway?

But you can propose your own version of the code without breaking the project structure.