Laravel 5.2中Form Request的UPDATE/PATCH条件唯一验证问题
解决Laravel 5.2 Form Request更新时唯一验证排除当前记录的问题
嘿,我来帮你搞定这个Laravel 5.2里的验证坑!你遇到的问题其实是没搞清楚Form Request里怎么正确获取更新记录的ID,还有unique规则的正确用法,咱们一步步来解决:
问题根源分析
- 用
$this->get('id')失效:因为你的PATCH请求的ID大概率是通过路由参数传递的(比如路由是/books/{id}),而不是作为请求参数放在表单里,所以$this->get('id')根本拿不到值,自然排除不了当前记录。 - 用
$book->id报错:Form Request类里默认没有$book这个变量,除非你手动获取模型实例,不然直接用肯定会提示未定义。
具体解决办法
方法一:直接通过路由参数获取ID(最简便)
首先确认你的更新路由是类似这样的:
Route::patch('/books/{id}', 'BookController@update');
然后在BookRequest的rules()方法里,这样写验证规则:
public function rules() { // 基础验证规则 $rules = [ 'title' => 'required|max:255', // 其他字段的验证规则... ]; // 针对更新请求(PATCH/PUT)修改唯一验证规则 if ($this->isMethod('patch') || $this->isMethod('put')) { // 从路由参数里拿到当前要更新的书籍ID $bookId = $this->route('id'); // 给对应字段追加unique规则,格式:unique:表名,字段名,要排除的ID $rules['title'] .= "|unique:books,title,$bookId"; // 如果你表的主键不是默认的`id`,还要加上主键字段名,比如主键是`book_id`: // $rules['title'] .= "|unique:books,title,$bookId,book_id"; } else { // 新增请求的唯一验证(不需要排除) $rules['title'] .= "|unique:books"; } return $rules; }
这个方法的核心是用$this->route('id')获取路由里的ID,而不是从请求参数里拿,因为更新操作的ID通常都是路由参数传递的。
方法二:先获取模型实例再用ID(适合需要用到模型其他属性的场景)
如果你除了ID还需要用到书籍模型的其他属性,可以在Form Request的构造函数里先查询模型:
use App\Book; class BookRequest extends Request { protected $book; public function __construct() { // 通过路由参数查询当前书籍模型 $this->book = Book::findOrFail($this->route('id')); } public function rules() { $rules = [ 'title' => 'required|max:255', // 其他规则... ]; if ($this->isMethod('patch')) { // 直接用模型的ID $rules['title'] .= "|unique:books,title," . $this->book->id; } else { $rules['title'] .= "|unique:books"; } return $rules; } // 别忘了authorize方法要返回true,不然验证不会生效 public function authorize() { return true; } }
这个方法适合你需要在验证逻辑里用到模型其他数据的情况,比如判断用户是否有权限修改这本书。
额外注意事项
- 确保你的
authorize()方法返回true(或者根据你的权限逻辑调整),否则Form Request会直接拒绝请求,不会执行验证。 - 替换代码里的
title和books为你实际要验证的字段名和表名。 - Laravel 5.2的unique规则格式是
unique:table,column,except,idColumn,其中except就是要排除的记录ID,idColumn是表的主键字段(默认是id,不需要改除非你自定义了主键)。
内容的提问来源于stack exchange,提问作者Yudy Ananda
相关产品推荐
相关产品推荐

