Laravel中无表单单方法实现增改+点赞功能点击报错排查
1. 如何在不使用表单的情况下,在一个方法中实现数据表的插入与更新操作?
咱们以Laravel为例来说,最省心的方式就是用Eloquent自带的updateOrCreate()方法——它能自动帮你判断数据是否存在:有就更新,没有就插入,完全不用依赖表单提交。
举个贴合你点赞场景的例子,比如要根据用户ID和帖子ID维护点赞记录:
public function handleLike($userId, $postId) { // 第一个参数是查询匹配条件,第二个是要插入/更新的字段 $like = Like::updateOrCreate( ['user_id' => $userId, 'post_id' => $postId], ['created_at' => now()] // 如果是更新场景,这里填要更新的字段就行 ); // 同步处理帖子点赞数 $post = Post::findOrFail($postId); // 根据是否是新创建的记录来增减点赞数(支持取消点赞逻辑) if ($like->wasRecentlyCreated) { $post->increment('like'); // 直接累加,比手动赋值更简洁 } else { $post->decrement('like'); $like->delete(); // 或者标记为已取消,看你的需求 } return redirect()->back(); }
核心逻辑就是先通过条件查询数据,存在就更新,不存在就插入,全程在方法内完成,和表单完全无关。要是用原生PHP或者其他框架,思路也一样:先查数据是否存在,再分支执行INSERT或者UPDATE语句。
2. 点赞功能报错排查与修复
先看你代码里最显眼的问题,也是大概率导致报错的原因:
问题1:请求方法不匹配
你的路由定义的是POST请求:
Route::post('like/{id}/{idpost}', 'HomeController@like')->name('likes');
但视图里用的是<a>标签,<a>默认发的是GET请求,这直接就会触发MethodNotAllowedHttpException(请求方法不允许)的错误。
修复方案:
把<a>改成表单提交,或者用AJAX发POST请求:
方案一:用表单包裹点赞按钮(最简单)
<form action="{{ route('likes', ['id' => Auth::user()->id, 'idpost' => $detail->id]) }}" method="POST"> @csrf <!-- 必须加,不然Laravel会拦截请求 --> <button type="submit" style="border: none; background: transparent; padding: 0;"> <i style="color: #ed4956; font-size: 25px;" class="fa fa-heart"></i> </button> </form>
方案二:AJAX实现无刷新点赞(体验更好)
<a href="javascript:void(0)" class="like-btn" data-user-id="{{ Auth::user()->id }}" data-post-id="{{ $detail->id }}"> <i style="color: #ed4956; font-size: 25px;" class="fa fa-heart"></i> </a> <!-- 记得在页面头部加CSRF元标签 --> <meta name="csrf-token" content="{{ csrf_token() }}"> <script> document.querySelector('.like-btn').addEventListener('click', function() { const userId = this.dataset.userId; const postId = this.dataset.postId; fetch(`/like/${userId}/${postId}`, { method: 'POST', headers: { 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content, 'Content-Type': 'application/json' } }).then(res => { if (res.ok) { // 这里可以直接更新页面上的点赞数,不用刷新整个页面 // 比如 document.querySelector('.like-count').textContent = parseInt(document.querySelector('.like-count').textContent) + 1; window.location.reload(); // 暂时先用刷新代替,后续可以优化 } }); }); </script>
其他潜在问题(提前避坑)
重复点赞导致数据冗余:你现在的代码没判断用户是否已经点过赞,每次点击都会插一条新的
like记录,点赞数会重复加,数据库也会有一堆重复数据。
修复:在插入前先查有没有已存在的点赞:public function like($id,$idpost) { $existingLike = Like::where('user_id', $id)->where('post_id', $idpost)->first(); $post = Post::findOrFail($idpost); if ($existingLike) { // 已点赞,取消点赞 $existingLike->delete(); $post->decrement('like'); } else { // 未点赞,新增记录 $like = new Like(); $like->user_id = $id; $like->post_id = $idpost; $like->save(); $post->increment('like'); } return redirect('post/'.$idpost); }冗余的数据库查询:你现在先
Post::find($idpost),又Post::where('id',$idpost)->value('like'),其实直接用$post->like就能拿到数值,而且用increment/decrement方法比手动赋值再保存更简洁高效。URL拼接不规范:视图里直接拼URL容易出错,建议用路由名称生成链接:
<!-- 原来的写法 --> <a href="{{url('like')}}/{{ Auth::user()->id }}/{{ $detail->id }}">...</a> <!-- 推荐写法,路由URL改了也不用改视图 --> <a href="{{ route('likes', ['id' => Auth::user()->id, 'idpost' => $detail->id]) }}">...</a>
内容的提问来源于stack exchange,提问作者Bima S M
相关产品推荐
相关产品推荐

