laravel 缓存 Eloquent 关系查询

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28844611/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 11:03:32  来源:igfitidea点击:

Cache Eloquent Relationship query

phplaraveleloquentlaravel-5

提问by FooBar

How can I cache this Eloquent query:

我如何缓存这个 Eloquent 查询:

dd($user->roles);

Because above will somehow trigger the $user->roles()query I assume.

因为上面会以某种方式触发$user->roles()我假设的查询。

I have tried with this:

我试过这个:

    public function roles() {
        return \Cache::remember('user_' . $this->id . '_roles', 10, function() {
            return $this->hasMany('App\Role');
        });
    }

But it does not work, because it has to return a array, not eloquent query.

但它不起作用,因为它必须返回一个数组,而不是雄辩的查询。

Any suggestions?

有什么建议?

回答by Bogdan

You can't store a relationship in the cache. You need to cache the actual data retrieved from the database. So you'll have something like this:

您不能在缓存中存储关系。您需要缓存从数据库中检索到的实际数据。所以你会有这样的事情:

public function roles()
{
    return \Cache::remember('user_' . $this->id . '_roles', 10, function()
    {
        return $this->hasMany('App\Role')->get()->toArray();
    });
}

And now you have to access it as a method, not a property, because it's not returning a relation anymore (and Eloquent would throw an exception):

现在你必须将它作为方法而不是属性来访问,因为它不再返回关系(并且 Eloquent 会抛出异常):

$user->roles();

Now you should get an array as you want.

现在你应该得到一个你想要的数组。

回答by MingalevME

Here is my approach:

这是我的方法:

public function bookmarks(): HasMany
{
    return $this->hasMany(Bookmark::class);
}

protected function getBookmarksCacheKey(): string
{
    return sprintf('user-%d-bookmarks', $this->id);
}

public function clearBookmarksCache(): bool
{
    return Cache::forget($this->getBookmarksCacheKey());
}

public function getBookmarksAttribute(): Collection
{
    if ($this->relationLoaded('bookmarks')) {
        return $this->getRelationValue('bookmarks');
    }

    $bookmarks = Cache::rememberForever($this->getBookmarksCacheKey(), function () {
        return $this->getRelationValue('bookmarks');
    });

    $this->setRelation('bookmarks', $bookmarks);

    return $bookmarks;
}

回答by Marcin Nabia?ek

If you want to cache user together with its roles you can do it this way:

如果您想将用户与其角色一起缓存,您可以这样做:

$user = User::find(1);
$user->load('roles');
Cache::put('users_'.$user->id, $user, 10);

I don't know why, but you need to use loadhere instead of with. If you used withyou would get error that you cannot cache PDOinstance.

我不知道为什么,但你需要使用loadhere 而不是with. 如果你使用with你会得到你不能缓存PDO实例的错误。