jessarcher / laravel-castable-data-transfer-object

Automatically cast JSON columns to rich PHP objects in Laravel using Spatie's data-transfer-object class
https://jessarcher.com/blog/casting-json-columns-to-value-objects/
MIT License
328 stars 23 forks source link

Creating a data-transfer-object with default values if the attribute value is null #10

Closed alexrififi closed 2 years ago

alexrififi commented 3 years ago

Hello Jess!

Thanks for your incredible work!

I have been using your magic package for a long time, but only recently encountered a problem. In my case i used laravel-castable-data-transfer-object for settings attribute and in some cases it's null.

It would be great if the value is null, then the data-transfer-object would be initialized with default values. spatie/data-transfer-object supports this since 1.6.5

This piece of code ... https://github.com/jessarcher/laravel-castable-data-transfer-object/blob/4b6015f689e0795c0f4b8a2dd06e50de1dbc391f/src/Casts/DataTransferObject.php#L21-L25

What if you do this?

        if (is_null($value)) {
            return new $this->class();
        }

Or you can give a choice of what to do in this case.

jessarcher commented 3 years ago

Hey @medvinator, thanks for the kind words!

I like this idea. I'm thinking of how we can make it configurable.

We could maybe do it using cast parameters so that it could be configured at the model level. Maybe something like:

protected $casts = [
    'settings' => Settings::class.':default', // Not sure on the naming here, but you get the idea
];

Otherwise we could add something to the DTO class itself so that it applies for all uses of the class. Perhaps a PHP8 attribute - I'm still trying to work out the appropriate uses cases for them.

What do you think?

alexrififi commented 3 years ago

I think it could be an Interface (like Laravel's \Illuminate\Contracts\Queue\ShouldQueue) or an PHP8 Attribute

Maybe like this

namespace App\DataTransferObjects;

use JessArcher\CastableDataTransferObject\Attributes\WithDefaults;
use JessArcher\CastableDataTransferObject\CastableDataTransferObject;

#[WithDefaults]
class ClientSettings extends CastableDataTransferObject
{
    public bool $pass_copyright = true;
}

or UseDefaults Attribute

Do as you like 😀

rroblik commented 2 years ago

Any news about it @jessarcher ? usefull to enforce JSON structure integrity

daraghoshea commented 2 years ago

I created a pull request (#13) that uses your suggestion of the Cast Parameter @jessarcher and was inspired by the nullable parameter on the Spatie Laravel Enum package.

Had to do some awkward workarounds to get it to work on a project, so thought I'd contribute a PR.

rroblik commented 2 years ago

Hope to see @daraghoshea work merged !

jessarcher commented 2 years ago

13 was merged and released in v2.2.0. Thank you to everyone for your contributions!