I am building a forum website using Laravel and Vue.
I have three tables: forums, posts, and users. One forum can have multiple posts, each post has a user who created the post.
When the user clicks on one forum, I want to display the latest 10 posts to this forum with the paginate method.
Forum.php
<?php namespace AppModels; use IlluminateDatabaseEloquentFactoriesHasFactory; use IlluminateDatabaseEloquentModel; class Forum extends Model { use HasFactory; protected $table = 'forums'; protected $guarded = []; /** * Get the forum posts * @return IlluminateDatabaseEloquentRelationsHasMany */ public function posts() { return $this->hasMany(Post::class)->orderBy('created_at', 'DESC'); } }
Post.php
<?php namespace AppModels; use IlluminateDatabaseEloquentFactoriesHasFactory; use IlluminateDatabaseEloquentModel; class Post extends Model { use HasFactory; protected $table = 'posts'; protected $guarded = []; /** * Get the post's user * @return IlluminateDatabaseEloquentRelationsBelongsTo */ public function user() { return $this->belongsTo(User::class); } }
User.php
<?php namespace AppModels; use IlluminateContractsAuthMustVerifyEmail; use IlluminateDatabaseEloquentFactoriesHasFactory; use IlluminateFoundationAuthUser as Authenticatable; use IlluminateNotificationsNotifiable; class User extends Authenticatable { use HasFactory, Notifiable; /** * The attributes that should be hidden for arrays. * * @var array */ protected $hidden = [ 'password', 'remember_token', ]; /** * The attributes that should be cast to native types. * * @var array */ protected $casts = [ 'email_verified_at' => 'datetime', ]; /** * Get the user posts * @return IlluminateDatabaseEloquentRelationsHasMany */ public function posts() { return $this->hasMany(Post::class); } }
Here I retrieve the forum posts with the users.
ForumService.php
<?php namespace AppServices; use AppModelsForum; class ForumService { public static function getForumPosts($forumId) { $forum = Forum::with('posts.user')->find($forumId); dd($forum); } }
However, I want to retrieve only 10 posts and get each post’s user, so how do I do that in a relationship? The posts are paginated, but how to I get now the posting user? Because the dot syntax is applying to the user, therefore I paginate the user, not the posts.
ForumService.php
<?php namespace AppServices; use AppModelsForum; class ForumService { public static function getForumPosts($forumId) { $forum = Forum::with( [ 'posts' => function ($query) { // How do I get the post user? return $query->paginate(10); } ] )->find($forumId); dd($forum); } }
Advertisement
Answer
Just add the with
method inside the query scope of the function you have created.
$forum = Forum::with( [ 'posts' => function ($query) { // returns posts with user return $query->with('user')->paginate(10); } ] )->find($forumId);
Now you can access the first user with $forum->posts[0]->user
which will not query to the database but will prefetch the users and populate it in paginator collection.