Laravel API点赞/点踩功能异常:状态返回与实际数据不符
Laravel点赞/点踩API:更新记录时
like字段始终设为1的问题 问题背景
你正在Laravel项目中实现点赞与点踩API,路由配置为:
Route::post('like', 'Api\ApiController@like');
控制器中的like方法代码如下:
$post = \App\Post::find($request->id); $social = SocialPost::where([['user_id', '=', ($request->user_id)],['post_id', '=', ($request->id)]])->first(); $unsocial = SocialPost::where([['user_id', '=', ($request->user_id)],['post_id', '=', ($request->id)],['like', '=', 0]])->first(); if ($social) { if ($unsocial) { $social->update(['like' => 1]); return json_encode(array('status' => true,'msg'=>'like')); } else { $social->update(['like' => 0]); return json_encode(array('status' => true,'msg'=>'dislike')); } } else { $join = new \App\SocialPost; $join->user_id = $request->user_id; $join->post_id = $post->id; $join->like = 1; $join->view = 0; $join->creator = 1; $join->save(); return json_encode(array('status' => true,'msg'=>'New table')); }
你遇到的问题是:第一个if分支(创建新记录)正常运行,但第二个分支(更新已有记录)存在异常——当对应的记录已存在时,即便返回的消息是'dislike',like字段的值始终被设为1。
问题分析&可能原因
冗余查询导致逻辑判断混乱
你的代码中,$social已经查询到了当前用户对应帖子的唯一记录(假设user_id和post_id是唯一约束的,这也是点赞系统的合理设计),但又额外查询了$unsocial。这不仅冗余,还可能因为查询时机的微小差异(比如并发操作)导致判断错误。批量赋值保护拦截了更新
如果你的SocialPost模型没有将like字段加入$fillable属性,Laravel的批量赋值保护会自动忽略update()方法中的like字段更新,导致字段值始终不变。逻辑判断的潜在歧义
当$social存在但$unsocial不存在时,你默认当前记录的like值是1,尝试将其改为0,但如果$social的like值本来就是0(比如之前的更新没生效),就会出现返回'dislike'但字段值还是1的矛盾情况。
解决方案
1. 修复模型的批量赋值设置
确保SocialPost模型中包含$fillable属性,允许like字段被批量赋值:
// app/SocialPost.php class SocialPost extends Model { protected $fillable = ['user_id', 'post_id', 'like', 'view', 'creator']; // ...其他代码 }
2. 简化逻辑,去掉冗余查询
直接使用已查询到的$social记录的like值来判断状态,避免重复查询:
public function like(Request $request) { // 用findOrFail更安全,若帖子不存在直接返回404 $post = \App\Post::findOrFail($request->id); $social = SocialPost::where([ 'user_id' => $request->user_id, 'post_id' => $request->id ])->first(); if ($social) { // 切换点赞状态:1变0,0变1 $newLikeStatus = $social->like === 1 ? 0 : 1; $social->update(['like' => $newLikeStatus]); $msg = $newLikeStatus === 1 ? 'like' : 'dislike'; return response()->json(['status' => true, 'msg' => $msg]); } else { // 创建新记录,用create()更简洁 SocialPost::create([ 'user_id' => $request->user_id, 'post_id' => $post->id, 'like' => 1, 'view' => 0, 'creator' => 1, ]); return response()->json(['status' => true, 'msg' => 'New table']); } }
3. 添加唯一索引防止重复记录
为了避免同一个用户对同一个帖子创建多条记录,建议给SocialPost表添加user_id和post_id的唯一联合索引:
ALTER TABLE social_posts ADD UNIQUE INDEX user_post_unique (user_id, post_id);
或者在迁移文件中设置:
// 迁移文件 $table->unique(['user_id', 'post_id']);
额外优化建议
- 使用Laravel自带的
response()->json()替代json_encode(),它会自动设置正确的HTTP头,更符合API规范。 - 对请求参数(
user_id、id)进行验证,比如在控制器中添加请求验证逻辑,避免非法参数导致的错误。
内容的提问来源于stack exchange,提问作者Gio Pac
相关产品推荐
相关产品推荐

