You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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。


问题分析&可能原因

  1. 冗余查询导致逻辑判断混乱
    你的代码中,$social已经查询到了当前用户对应帖子的唯一记录(假设user_id和post_id是唯一约束的,这也是点赞系统的合理设计),但又额外查询了$unsocial。这不仅冗余,还可能因为查询时机的微小差异(比如并发操作)导致判断错误。

  2. 批量赋值保护拦截了更新
    如果你的SocialPost模型没有将like字段加入$fillable属性,Laravel的批量赋值保护会自动忽略update()方法中的like字段更新,导致字段值始终不变。

  3. 逻辑判断的潜在歧义
    当$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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 07:44:47