缓存Eloquent Relationship查询

时间:2015-03-04 00:27:21

标签: php laravel eloquent laravel-5

如何缓存此Eloquent查询:

dd($user->roles);

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

我试过这个:

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

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

有什么建议吗?

3 个答案:

答案 0 :(得分:4)

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

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

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

$user->roles();

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

答案 1 :(得分:1)

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

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

我不知道为什么,但你需要在这里使用load而不是with。如果您使用with,则会收到无法缓存PDO实例的错误。

答案 2 :(得分:0)

这是我的方法:

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

    if (!$this->relationLoaded('bookmarks')) {
        $this->setRelation('bookmarks', $bookmarks);
    }

    return $bookmarks;
}
相关问题