商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > Laravel怎么实现点赞功能_Laravel用户互动功能开发【详解】

Laravel怎么实现点赞功能_Laravel用户互动功能开发【详解】

  发布于2026-07-09 阅读(0)

扫一扫,手机访问

说到 Lara vel 点赞功能,最稳妥的数据表结构是多态关联的中间表,而不是把点赞状态塞进 JSON 字段或布尔字段里应付了事。Eloquent 的 belongsToMany 关系天然适配“用户对某篇文章或评论点赞”这种场景,后续加时间戳、取消赞、统计数据等扩展也都方便。

常见错误是什么呢?有人把点赞状态存在 posts.is_liked_by_current_user 这类字段里,每次用户操作都要全表更新,而且查不了“谁点了赞”“点过几次”。这显然不是长久之计。

  • likes 表至少包含:user_idlikeable_idlikeable_type(实现多态)、created_at
  • 对应模型用 HasLikes trait 或直接在 PostComment 中定义 likers() 关系
  • 避免用 increment('likes_count') 做计数器——并发点赞时会丢数据;改用 likes()->count() 或带锁的原子更新

Lara vel怎么实现点赞功能_Lara vel用户互动功能开发【详解】

点赞逻辑该用 Eloquent 模型关系还是单独数据表

直接用 likes 表 + 多对多中间表结构最稳妥,别图省事用 JSON 字段或布尔字段硬塞。Eloquent 的 belongsToMany 关系天然适配“用户对某篇文章/评论点赞”这种场景,也方便后续加时间戳、取消赞、统计总数等扩展。

常见错误是把点赞状态存在 posts.is_liked_by_current_user 这类字段里——每次用户操作都要全表更新,且无法查“谁点了赞”“点过几次”。

  • likes 表至少包含:user_idlikeable_idlikeable_type(实现多态)、created_at
  • 对应模型用 HasLikes trait 或直接在 PostComment 中定义 likers() 关系
  • 避免用 increment('likes_count') 做计数器——并发点赞时会丢数据;改用 likes()->count() 或带锁的原子更新

Lara vel 10+ 中如何安全处理重复点赞请求

前端连点两次、刷新后重发、接口被脚本调用……这些都会导致重复插入 likes 记录。靠数据库唯一索引比 PHP 层判断更可靠。

必须给 likes 表加联合唯一约束:UNIQUE(user_id, likeable_id, likeable_type)。Lara vel 迁移里写成:

Schema::create('likes', function (Blueprint $table) {    $table->id();    $table->foreignId('user_id')->constrained()->cascadeOnDelete();    $table->unsignedBigInteger('likeable_id');    $table->string('likeable_type');    $table->timestamps();    $table->unique(['user_id', 'likeable_id', 'likeable_type']);});

插入失败时捕获 Illuminate\Database\QueryException,检查错误码是否为 23000(唯一约束冲突),再返回 409 或静默忽略。

  • 别在控制器里先 where() 查一遍再插入——竞态条件依然存在
  • 不要用 firstOrCreate() 替代唯一索引——它仍可能因并发漏判
  • 前端按钮点击后立即置灰,配合防抖,但后端校验不可省

API 接口怎么返回当前用户是否已点赞

不能每次查列表都 N+1 加载 likers 关系。正确做法是在查询主资源时预加载一个“当前用户是否点赞”的标记字段,用子查询或关联聚合。

推荐用 Lara vel 的 withCount() 配合条件约束:

$posts = Post::withCount(['likers as is_liked' => function ($q) {    $q->where('user_id', auth()->id());}])->get();

这样每个 $post 会带一个 is_liked_count 字段(0 或 1),前端直接判断即可。注意字段名是 is_liked_count,不是 is_liked

  • 别在循环里对每个 $post 调用 $post->likers()->where('user_id', ...)->exists()
  • 如果用 API Resource,记得在 toArray() 里把 is_liked_count > 0 转成布尔值返回
  • 未登录用户要提前过滤掉 auth()->id(),否则报错

软删除模型点赞时要注意什么

当被点赞的模型(比如 Post)启用了软删除,likes 表里仍会存着指向已删除记录的 likeable_id。这会导致 likers() 关系查不到数据,withCount() 统计变少,甚至关联查询报错。

解决方案不是删 likes 记录,而是让关系自动忽略软删除模型:

public function likers(){    return $this->morphToMany(User::class, 'likeable')                ->withoutTrashed(); // 关键}

同时确保迁移中 likeable_id 字段允许为 NULL(万一目标模型被强制删除),并在业务逻辑里考虑“点赞对象不存在了”该如何展示(比如显示“内容已不可见”)。

  • 别依赖数据库外键级联删除——软删除不触发外键动作
  • withoutTrashed() 必须显式加,Eloquent 默认不跳过软删除模型
  • 如果需要保留历史点赞数据(比如审计),就别删 likes,只清理无效关联的展示逻辑

其实总结下来就三件事:多态关联字段类型、唯一索引覆盖范围、软删除穿透控制。这三个地方一旦漏掉,上线后就容易出现“点不动”“数不对”“查崩溃”的尴尬局面。细节都在迁移和关系定义里,不在控制器里。

本文转载于:https://www.php.cn/faq/2413670.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注