Open AliN11 opened 5 years ago
This would be useful for example when I have posts and want to cache only their comments.
I don't understand your question. For each model, relations are only loaded the first time they're "requested". This most commonly happens via ->relation
or using ->with()
on the query. So in a sense, they are cached.
What your example caches is the "definition of the relation", something different.
Maybe we need more information, but currently it's not clear what problem you have/try to solve 🤷♀️
@mfn Thanks for reviewing. It's simple. For example we have posts and comments in our website. A post has 40 comments and no new comment has been posted for a while. So it is better to cache these comments instead of fetching them from DB on every page load.
What you mentioned, works only for one page request. I mean if I refresh the page, nothing caches.
@AliN11 perhaps the laravel-model-caching package by @mikebronner will suit your needs.
@drbyte It's cool. But it doesn't cache a specific relationship.
I'm still not clear on your goal but I'm trying to summarize it: you want to cache (all/specific?) relations on a model across requests?
I understand what is an @AliN11 goal. for example if you have 1 post and that post have 20 comments, with this code:
$post = Post::with('comments')->find(1);
two DB queries are excecuted :
select * from posts ...
//and
select * from comments
for same code from above, he want only one query
select * from posts ...
and get comments from cache...
@mfn, Exactly what @fico7489 said.
// Models\User.php
public static function all()
{
$minsPerDay = 1440;
return $users = Cache::remember('users', $minsPerDay, function() {
return User::all();
});
}
You know above code caches users for 24 hours and keeps output in the filesystem, Redis, etc. So it means that we have only one query to DB per day, no matter how many visits our page/application has.
But there is no way to apply above code in relationships. So you can't cache queries within relationships.
So think of that what happens if our page has 300K views per day and you call $post->comments
on every request.
So think of that what happens if our page has 300K views per day and you call
$post->comments
on every request.
Probably nothing scary, since simple SELECT
queries utilizing indexes are pretty quick and should be automatically cached by the database engine anyway.
One way or another: instead of sending 300K queries to a multi-threaded MySQL / MariaDB / Postgres, you're now sending 300K queries to a single-threaded Redis or (even worse!) the filesystem itself, so nothing really changed.
@Patryk27 You are right but I don't mean that. It was just an example. Examples are always simple :D Sometimes before performing cache, data are processed and mixed with some other data and queries. That's why caching is useful. It prevents duplicate calculation and processing.
Well then - show a more complex example that could be solved inside the framework :-)
As for now, I think that it seems more like a domain-related thing that should be handled entirely by the application, not framework.
@Patryk27 I know there are some tricky ways, however $post->comments
is impossible to cache.
however
$post->comments
is impossible to cache
Did you try with a custom getter or are they overridden in such a case?
@mfn I tried. If we override the __get
method which exists in Illuminate\Database\Eloquent\Model
, We can't use any other relationships like this: $post->likes
anymore.
If we use __get()
like bellow:
public function comments()
{
return $this->belongsTo('App\Models\Comment');
}
public function __get($name)
{
return $name;
}
And if we try $post->comments
, the getter executes and comments()
method is ignored. It means that all relationships are ignored by adding __get()
Sorry I meant getCommentsAttribute
, did you try that?
@mfn No I'll try that.
Don't know if still relevant, anyway I think this could help in such scenario:
Hi. I searched the web and I think there is no way to cache an eloquent relationship. This would be useful for example when I have posts and want to cache only their comments.