Below is the code I have to fetch all Discussions
with the associated threads
and posts
. I am trying to limit the number of posts to 1. When I do this, I expect for each thread to have only 1 post in it, however 9 threads have no posts in them and 1 thread has 1 post in it.
App\Discussion::with([
'threads' => function ($query) => {
// Correctly limits the number of threads to 10.
$query->latest()->take(10);
},
'threads.posts' => function ($query) {
// Limits all posts to 1, not each post to 1 for each thread.
$query->take(1);
}
])->where(['slug' => 'something'])->firstOrFail();
The code above runs the following SQL queries in the database.
select * from `discussions` where (`slug` = ?) and `discussions`.`deleted_at` is null limit 1
select * from `threads` where `threads`.`discussion_id` in (?) and `threads`.`deleted_at` is null order by `created_at` desc limit 10
select * from `posts` where `posts`.`thread_id` in (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) and `posts`.`deleted_at` is null order by `created_at` desc limit 1
I can see the third query is the one causing the issue as it's limiting all posts to 1.
I expect to see the following; one discussion, with 10 threads and 1 post in that thread.
{
"id": 1,
"title": "Discussion Title",
...
"threads": [
{
"id": 1,
"title": "Thread Title",
...
"posts": [
{
"id": 1,
"title": "Post Title",
...
}
]
}
...
]
}
Is there a way to do this within the Laravel framework or will I have to run raw queries? I would prefer to stick with the Eloquent ORM as much as possible.
You need to make a few "tweaks", as Eloquent does not have a query method to limit the number results in a relation.
First create this function on your Thread model.
public function one_post()
{
//OrderBy is optional
return $this->hasOne(Post::class)->orderBy('id', 'asc');
}
Now you have a relation that will only return one post. You can have your query this way:
App\Discussion::with([
'threads' => function ($query) {
// Correctly limits the number of threads to 10.
$query
->latest()
->take(10)
->with('one_post');
}
])->where(['slug' => 'something'])->firstOrFail();
Eager result cannot be easily limited, but according to: https://laracasts.com/discuss/channels/eloquent/laravel-51-eloquent-relationship-hasmany-limit-records can be mapped using the model relation....in other words your code could look something like:
App\Discussion::with([
'threads' => function ($query) => {
// Correctly limits the number of threads to 10.
$query->latest()->take(10);
}])->where(['slug' => 'something'])->firstOrFail()
->map(function ($thread) {
$thread->setRelation('posts', $thread->posts->take(1));
return $thread;
});
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.