skip to Main Content

My website incorporates multilingual functionality, allowing content to be displayed in various languages. To facilitate this, language-specific data is stored in the MySQL database within JSON fields. This approach enables flexible storage of language-specific information, with each JSON field containing data in different languages.

Example of the table:

articles – title – json – example:

{"en": "English Title", "es": "Título en Español", "id": "Judul dalam Bahasa Indonesia"}

And this is my Article model:

protected function casts(): array
{
    return [
        'title' => 'json',
        'resume' => 'json',
        'content' => 'json',
    ];
}

I tried to retrieve only the desired language value from the JSON attribute in my Laravel model using the following approach:

protected function title(): Attribute
{
    return Attribute::make(
        get: fn ($value) => $value['en'],
        set: fn ($value) => $value['en'],
    );
}

Despite various attempts, I’m still unable to retrieve only the desired language value. When attempting to access the specific language using syntax like $value->en, I encounter errors such as "Cannot access offset of type string on string".

My objective is to receive JSON data from articles in the format like articles[{ "id" : 1, "title" : "english title"}], containing only the necessary language data. However, I’m currently receiving the entire JSON object instead.

I’ve explored using Laravel’s JSON.php class as documented, but the issue persists.

Additionally, I tried the following alternative approach:

protected function getTitleAttribute() { return $this->title['en']; }

However, the problem remains unresolved.

In summary, I’m struggling to access a single value from the JSON attribute in my model, and even defining a cast hasn’t resolved the issue. This limitation hampers my ability to efficiently transmit only the necessary data to my React frontend.

2

Answers


  1. For one language only you can do something like this:

    public function getTitleAttribute($value) { 
        return $value['en']; 
    }
    
    public function setTitleAttribute($value)
    {
        $this->attributes['title']['en] = value;
    }
    

    For multiple languages I would use something else:

    public function getTitleByLanguage($language)
    {
        return isset(this->title[$language]) ? this->title[$language] : 
             "No translation to ". $language . " available";
    }
    
    public function setTitleByLanguage($language, $value)
    {
        $this->attributes['title'][$language] = $value;
    }
    

    I didn’t test any of these methods, so please excuse potential typos 🙂 I’m just trying to get you on the right path.

    Addition
    As by @9uifranco mentioned you should cast to array instead of json. Sorry didn’t see that at first.

    Login or Signup to reply.
  2. You can cast your attributes to array instead, and then get the value you want:

    protected function casts(): array
    {
        return [
            'title' => 'array',
            'resume' => 'array',
            'content' => 'array'
        ];
    }
    

    or just use the $casts attribute:

    public $casts = [
        'title' => 'array',
        'resume' => 'array',
        'content' => 'array'
    ];
    

    And then get the correct value by language:

    public function getTitleByLang($lang) { 
        return $this->attributes['title'][$lang] ?? null;
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search