Laravel中通过REST API删除关联数据的实现方法
问题描述
我拥有Book和BookReview两个数据库表,表结构关系如下:
- Book表:与
BookReview为一对多关联,包含书籍基础字段(如id、书名等) - BookReview表:与
Book为多对一关联,包含id、book_id(关联Book表的外键)、评论内容等字段
已定义的模型关联代码:
Book模型
public function reviews() { return $this->hasMany(BookReview::class); }
BookReview模型
public function book() { return $this->belongsTo(Book::class); }
路由已配置:
Route::delete('/books/{bookId}/reviews/{reviewId}');
当前控制器的destroy方法代码如下:
public function destroy(int $bookId, int $reviewId, Request $request) { // TODO: implement $check_bookReview = BookReview::firstWhere('id', $reviewId); if ($check_bookReview) { BookReview::destroy($id); return response()->noContent(); } else { abort(404); } }
我此前从未处理过关联数据的删除操作,请问该如何完成此功能?
解决方案
你的现有代码存在两个核心问题:一是使用了未定义的变量$id,二是没有验证待删评论是否属于URL中指定的书籍,存在越权删除的风险。下面提供两种可靠的实现方式:
方式一:通过书籍关联查询并删除
先定位目标书籍,再从它的关联评论集合中找到待删条目,天然保证评论归属的正确性:
public function destroy(int $bookId, int $reviewId, Request $request) { // 查找指定书籍,不存在则直接返回404 $book = Book::findOrFail($bookId); // 从书籍的关联评论中定位待删条目,不存在则返回404 $review = $book->reviews()->findOrFail($reviewId); // 执行删除 $review->delete(); return response()->noContent(); }
方式二:直接查询并验证归属
若不想先查询书籍,可直接查询评论并校验其book_id与传入的$bookId是否匹配:
public function destroy(int $bookId, int $reviewId, Request $request) { // 查找评论同时验证归属,不满足则返回404 $review = BookReview::where('id', $reviewId) ->where('book_id', $bookId) ->firstOrFail(); // 执行删除 $review->delete(); return response()->noContent(); }
关键注意点
- 归属验证:必须确保待删评论属于URL中指定的书籍,避免用户删除不属于自己权限范围内的评论
- 错误处理:使用
findOrFail()或firstOrFail()可以自动触发404响应,无需手动判断数据是否存在 - 变量修正:原代码中
BookReview::destroy($id)的$id是未定义变量,应替换为$reviewId,但先查询再调用delete()的逻辑更清晰可控
内容的提问来源于stack exchange,提问作者info.dava
相关产品推荐
相关产品推荐

