There is a model Country
and relation translations
as follows
<?php
namespace Modules\User\Entities;
use Astrotomic\Translatable\Translatable;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Cache;
use Modules\Core\Traits\Rememberable;
use Modules\User\Entities\Sentinel\User;
class Country extends Model
{
use Rememberable;
use Translatable;
protected $table = 'countries';
public $translatedAttributes = ['name'];
protected $fillable = [
'name',
'code',
'weight',
];
// protected $rememberCacheTag = 'countries';
public function users()
{
return $this->hasMany(User::class, 'country_id');
}
protected static function booted()
{
static::addGlobalScope('lang', function (Builder $builder) {
$builder->whereHas('translations', function (Builder $q) {
$q->where('locale', App::getLocale());
});
});
}
public function translations(): HasMany
{
return $this->hasMany($this->getTranslationModelName(), $this->getTranslationRelationKey());
}
}
I need to cache the data of the translations
relation. I have tried the following so far that taken from Link
$c = Country::with([
'translations' => function($q){
$q->remember(600);
}
])->remember(600)->find($this->country_id);
and this solution too
public function translations(): HasMany
{
return $this->hasMany($this->getTranslationModelName(), $this->getTranslationRelationKey())->remember(600);
}
But I got the error
Call to undefined method Illuminate\Database\Eloquent\Relations\HasMany::remember()
How can I cache the data retrieved from a relation?
You should cache the entire query, since just caching the relation does not work. (At least out of the box, unsure if you can 'hack' it)
So, using Laravel Cache, it becomes as follows;
$countryId = $this->countryId;
return Cache::remember("<your_cache_key>", 600, function() use ($countryId) {
return Country::with(['translations'])->find($countryId);
});
If you are using Redis/Predis (or anything else that supports cache tagging), you can even add cache tags to it;
$countryId = $this->countryId;
return Cache::tags([<array_of_cache_tags>])->remember("<your_cache_key>", 600, function() use ($countryId) {
return Country::with(['translations'])->find($countryId);
});
In the example <your_cache_key>
could be something along the lines of "country_translations:{$countryId}"
.
<array_of_cache_tags>
could be something like ["country", "translations"]