Laravel查询需求:获取带创建者信息及当前用户点赞标记的帖子列表
Laravel 查询修正方案:避免帖子重复并正确返回点赞标记
问题根源
直接关联 post_likes 表会导致重复数据——同一帖子被多个用户点赞时,每条点赞记录都会生成一条重复的帖子数据。解决核心是不通过关联查询拉取所有点赞记录,而是通过子查询/条件统计判断当前用户是否点赞。
方案1:Eloquent 条件统计(推荐)
利用 withCount 统计当前用户对单帖的点赞数,再转成布尔标记,同时加载帖子创建者信息:
$currentUserId = auth()->id(); $posts = Post::with('user:id,username,profile_pic,email') // 仅加载需要的用户字段,优化性能 ->withCount([ 'postLikes as liked' => function ($query) use ($currentUserId) { $query->where('user_id', $currentUserId); } ]) ->get() ->map(function ($post) { // 把统计数转成布尔标记:大于0则已点赞 $post->liked = $post->liked > 0; return $post; });
方案2:子查询判断存在性
通过 selectSub 编写子查询,直接判断当前用户是否给该帖子点赞:
$currentUserId = auth()->id(); $posts = Post::select('posts.*') ->selectSub(function ($query) use ($currentUserId) { $query->selectRaw('1') ->from('post_likes') ->whereColumn('post_likes.post_id', 'posts.id') ->where('post_likes.user_id', $currentUserId); }, 'liked') ->with('user:id,username,profile_pic,email') ->get() ->map(function ($post) { // 子查询无结果时返回null,转成false $post->liked = !is_null($post->liked); return $post; });
方案3:原生SQL查询
如果偏好原生查询,用 EXISTS 子句判断点赞状态:
$currentUserId = auth()->id(); $posts = DB::table('posts') ->select([ 'posts.*', 'users.username', 'users.profile_pic', 'users.email', DB::raw('CASE WHEN EXISTS (SELECT 1 FROM post_likes WHERE post_likes.post_id = posts.id AND post_likes.user_id = ?) THEN 1 ELSE 0 END AS liked') ]) ->join('users', 'posts.user_id', '=', 'users.id') ->setBindings([$currentUserId]) ->get();
必要的模型关联配置
确保你的 Eloquent 模型配置了正确的关联关系:
User 模型
class User extends Model { public function posts() { return $this->hasMany(Post::class); } public function postLikes() { return $this->hasMany(PostLike::class); } }
Post 模型
class Post extends Model { public function user() { return $this->belongsTo(User::class); } public function postLikes() { return $this->hasMany(PostLike::class); } }
PostLike 模型
class PostLike extends Model { public function post() { return $this->belongsTo(Post::class); } public function user() { return $this->belongsTo(User::class); } }
内容的提问来源于stack exchange,提问作者Richsmi23
相关产品推荐
相关产品推荐

