Laravel怎么实现点赞收藏功能_Laravel多态关联Polymorphic使用【实战】

1次阅读

点赞和收藏必须用多态关联,因为需统一处理post、comment、video等多种模型的交互行为;通过likes表的likeable_type和likeable_id字段动态关联,配合联合唯一索引防止重复,并在模型中正确定义morphto/morphmany关系。

Laravel怎么实现点赞收藏功能_Laravel多态关联Polymorphic使用【实战】

点赞和收藏为什么必须用多态关联

因为点赞(like)和收藏(favorite)行为可能发生在多种模型上——比如 PostCommentVideo,而你不可能为每种组合都建一张表(post_likescomment_likes…)。laravel 的多态关联用一张 likes 表就能统一处理,靠 likeable_typelikeable_id 两个字段动态指向任意模型。

如何定义 Like 和 Favorite 模型及迁移

别拆成两张表,统一用 interactions 表更灵活(或按业务拆成 likesfavorites,但结构一致)。以 likes 为例:

php artisan make:migration create_likes_table

迁移里定义:

  • user_id:谁点的
  • likeable_type字符串,如 AppModelsPost
  • likeable_id:对应模型主键值
  • 联合唯一索引:(user_id, likeable_type, likeable_id),防止重复点赞

模型 Like 中定义多态关系:

public function likeable() {     return $this->morphTo(); }

在 Post/Comment 等被操作模型中声明多态关系

比如 Post 模型要支持被点赞,就在类里加:

public function likes() {     return $this->morphMany(Like::class, 'likeable'); }

同理,CommentVideo 都加这一行。注意参数顺序:morphMany(模型类, 多态字段前缀),这里前缀是 likeable,所以数据库字段是 likeable_typelikeable_id

常见错误:

  • likeable 写成 likeliked,导致字段名不匹配
  • 迁移里漏掉 likeable_typeindex,查某篇文章所有点赞时性能暴跌
  • 没设联合唯一索引,用户手抖连点两次就存了两条重复记录

实际使用:点赞/取消点赞的逻辑怎么写

核心是先查是否存在,再决定 insert 或 delete。别用 updateOrCreate —— 它无法安全处理多态字段的复合条件。

推荐写法:

$like = $post->likes()->where('user_id', auth()->id())->first();  if ($like) {     $like->delete(); } else {     $post->likes()->create(['user_id' => auth()->id()]); }

更简洁可复用的方式是封装到 trait 或 service 中,但关键点就两个:

  • 必须用 where 显式查 user_id + 多态模型 ID,不能只依赖 auth()->id() 就 create
  • 前端触发时,接口返回当前状态(已点赞 / 未点赞),避免客户端靠 toggle 按钮状态出错

多态本身不难,难的是在高并发场景下保证“点一下只生效一次”,这得靠数据库唯一索引兜底,而不是靠 PHP 层判断。

text=ZqhQzanResources