2

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 2

0

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Hey, thank you for your support, i casted it like you said and i got this: Cannot access offset of type string on string. and in mysql database its the field is set to json `` protected function casts(): array { return [ 'title' => 'array', 'resume' => 'array', 'content' => 'array', ]; } public function getTitleAttribute($value) { return $value['en']; } public function setTitleAttribute($value) { $this->attributes['title']['en'] = $value; }``
0

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;
}

5 Comments

Thank you for your support, with your function i got [Undefined property: App\Models\Article::$title]
Try to change getTitleByLang function to this: return $this->attributes['title'][$lang] ?? null;. I will edit my answer.
i still get Cannot access offset of type string on string, it's like the json is not being casted as array
i tried to access it in a for each loop and i got that is really an array: array(3) { ["en"]=> string(13) "english title" ["id"]=> string(8) "id title" ["pt"]=> string(8) "pt title" }
That's weird behavior.. Can you complement your question with what you've tried so far (that will help for debugging)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.