Skip to content

Eloquent cast is always detected as dirty #1032

@SanderSander

Description

@SanderSander

✏️ Describe the bug
When we use a Data object in a eloquent model cast, that field will always be marked as dirty even if nothing has changed.

Explanation

When retrieving a JSON field from the database it will result in a string {"x": "hello world"} note the space after the colon also the order of the fields can be different. This is the behavior of MySQL. And I also saw the issue here for Postgres #496

While the behavior of json_encode PHP results in the string {"x":"hello world"}.

In eloquent itself there is a separated check for object and collection casts
https://github.com/laravel/framework/blob/12.x/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php#L2244

But this doesn't exists for custom casts, I created a PR in laravel laravel/framework#55945 to add the ability to do custom value checks to detect if an attribute is dirty or not.

I hope it will be merged or another option will be created, after that this issue could be resolved by adding something like the following to the DataEloquentCast to fix this issue.

    /**
     * Compare the two values, and check if they are equal
     */
    public function compare($model, string $key, $value1, $value2): bool
    {
        // Compare the two values loosly
        return json_decode($value1) == json_decode($value2);
    }

✅ Expected behavior
I would expect the $model->isDirty() to return false if nothing has changed.

🖥️ Versions

Laravel: 12.17.0
Laravel Data: 4.15.1
PHP: 8.4.7
Database: MySQL (ver. 8.0.36)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions