Cache Eloquent Relationship query Cache Eloquent Relationship query php php

Cache Eloquent Relationship query


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


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):

$user->roles();

Now you should get an array as you want.


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 load here instead of with. If you used with you would get error that you cannot cache PDO instance.