【问题标题】:Cache Eloquent Relationship query缓存 Eloquent 关系查询
【发布时间】:2015-03-04 00:27:21
【问题描述】:

如何缓存这个 Eloquent 查询:

dd($user->roles);

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

我试过这个:

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

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

有什么建议吗?

【问题讨论】:

标签: php laravel eloquent laravel-5


【解决方案1】:

这是我的方法:

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

【讨论】:

  • 这是最完整的答案,很棒的工作。但是,额外的 !$this->relationLoaded 检查是多余的,因为您在将值分配给 $bookmarks 变量之前已经检查过它。
  • 这正是我想要的……谢谢!
  • 谢谢!然而,至少在 Laravel 9 中,if ($this->relationLoaded('bookmarks')) { 块不是必需的,因为 getRelationValue 方法无论如何都会检查这个
【解决方案2】:

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

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

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

$user->roles();

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

【讨论】:

  • 但这是一种探测方式吗?我猜 has Many 关系总是要返回“hasmany”属性?...
  • 如果你想无缝地获取关系的缓存结果,这很好。 roles 方法不需要返回关系对象。但是,如果您想在某些地方使用关系而不使用缓存,您可以使用 roles 方法返回常规关系,以及另一种方法,例如返回缓存数据的 cachedRoles。这应该更容易看出区别。
  • 尝试使用此代码时出现错误。这就是我得到的Call to a member function addEagerConstraints() on array
【解决方案3】:

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

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

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

【讨论】:

  • 它是这样工作的,因为您现在正在执行“延迟加载”。您正在加载已获取的 eloquent 模型的相关模型。
  • 如何将其转换回具有角色关系的用户模型?
猜你喜欢
  • 1970-01-01
  • 2013-11-30
  • 2021-06-10
  • 2013-10-03
  • 2017-07-19
  • 1970-01-01
  • 1970-01-01
  • 2021-09-25
  • 2015-01-21
相关资源
最近更新 更多