英文:
Laravel: How to cache the data retrieved from a relationship of a model?
问题
以下是您提供的代码的翻译部分:
有一个名为 `Country` 的模型和名为 `translations` 的关系,如下所示
<?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());
}
}
如果您想要缓存translations
关系的数据,您可以尝试以下两种方法:
第一种方法:
$c = Country::with([
'translations' => function ($q) {
$q->remember(600);
}
])->remember(600)->find($this->country_id);
第二种方法:
public function translations(): HasMany
{
return $this->hasMany($this->getTranslationModelName(), $this->getTranslationRelationKey())->remember(600);
}
但是,如果您遇到以下错误:
Call to undefined method Illuminate\Database\Eloquent\Relations\HasMany::remember()
这意味着remember
方法不适用于HasMany
关系。您可以考虑在查询Country
模型之后手动缓存translations
关系的数据,而不是在关系定义中使用remember
方法。这可以通过Laravel的缓存功能来实现。
英文:
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?
答案1
得分: 1
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"]
.
英文:
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"]
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论