spatie / laravel-translatable

Making Eloquent models translatable
https://spatie.be/docs/laravel-translatable
MIT License
2.26k stars 281 forks source link

Accessors on translatable attributes no longer returning json values #444

Closed blackjak231 closed 7 months ago

blackjak231 commented 7 months ago

Hey !

I've been using a custom Trait mentioned here for 2 years now without any problems. To summarize, I have the following Trait with mutators :

trait TranslateMethods
{
    public function getTranslatedAttribute($value)
    {
        if ($json = json_decode($value)) {
            return $json->{app()->getLocale()} ?? "";
        }
        return $value;
    }
}
public $translatable = [
    'title'
];

// ...

protected function title(): Attribute
{
    return Attribute::make(
        get: fn ($value) => $this->getTranslatedAttribute($value),
    );
}

So far, $value has always been equal to the json/array value of the attribute. However, since upgrading to Laravel 11, it seems the Attribute or event the Casting logic has changed and $value goes through each translation string in the array individually.

Here is an example of what I mean : Let's imaging a title attribute with the following value (in DB) :

{
    'fr': 'Mon titre',
    'en': 'My title'
}

and the following mutator

protected function title(): Attribute
{
    return Attribute::make(
        get: fn ($value) => Log::info($value),
    );
}

And a simple controller method :

public function index(Request $request)
{
    $pages = Page::ordered()->get();
    return  response()->json(compact('pages'));
}

On Laravel 10, Log::info would only log {'fr': 'Mon titre','en': 'My title'}. If i don't log the value and us the getTranslatedAttribute method it returns only the translated title of the current Locale.

On Laravel 11, it logs Mon titre and then another log My title. If i don't log the value and us the getTranslatedAttribute method it returns the full json.

I've been trying to go deeper into this library and into the way Laravel casting/mutaitng works but I've reached my max understanding after a few hours of digging...

Is anyone able to reproduce this and able to help me wrap my head around this issue ? What changed and could anything be fixed in the package ?

Thanks !

FYI: I'm aware I could always do the following :

protected function title(): Attribute
{
    return Attribute::make(
        get: fn ($value,$attributes) => $this->getTranslatedAttribute($attributes['title']),
    );
}

However I want to limit the use of static array keys.