Laravel 8 单表单请求处理存储/更新校验时unique规则报非对象属性获取错误
报错根因
错误触发的核心是:新增场景下路由不存在Post模型绑定实例,此时$this->post为null,直接访问->id属性就会抛出非对象取属性的错误。
你的写法能在更新场景正常运行,是因为更新路由(如/posts/{post})开启了Laravel隐式模型绑定,能正确解析出对应的Post实例;但新增场景的路由(如/posts)没有这个参数,自然拿不到对应的对象。
适配多场景的修复方案
方案1:使用Laravel内置optional()辅助函数做空值兼容(改动最小)
直接对访问的post属性做空值包裹,即使对象不存在也不会触发报错:
public function rules() { return [ 'user_id' => ['required'], 'category_id' => ['required'], 'title' => [ 'required', 'max:20', Rule::unique('posts')->ignore(optional($this->post)->id) ], 'body' => ['required'], 'picture' => ['required'], 'study_time' => ['required','numeric','max:120'], // 原代码max规则值为空,需补上具体数值 'tags' => ['required'], 'status' => ['required'], ]; }
实现逻辑:
optional()是Laravel内置辅助函数,会判断传入的值是否为有效对象,非对象场景下访问任意属性都会返回null,不会触发非对象属性访问错误- 当
ignore()方法收到null参数时,不会在唯一值校验中添加排除条件,会严格校验全表范围内该字段的唯一性,完全匹配新增场景的校验需求 - 当更新场景下
$this->post有效时,会正确传入对应记录的id,自动在唯一值查询中排除当前记录,避免将记录自身的字段值判定为重复
方案2:直接从路由参数取值,代码更简洁
不依赖控制器的模型属性赋值,直接从当前路由解析参数,自动适配两个场景的逻辑:
'title' => [ 'required', 'max:20', Rule::unique('posts')->ignore($this->route('post')) ]
实现逻辑:Laravel的路由解析方法如果检测到路由参数绑定了模型实例,会自动返回对应模型的主键值;如果当前路由没有对应参数,会直接返回null,和方案1的效果完全一致。
代码额外修正提醒
- 自定义校验消息方法名拼写错误:Laravel 框架要求的自定义消息方法名是
messages(),当前代码写的message()不会被框架识别,会导致你配置的波斯语校验提示完全不生效,需要修正拼写。 study_time校验规则中max:没有填写限制数值,属于不完整规则,不会生效,需要补上具体允许的最大值。
内容的提问来源于stack exchange,提问作者calisa
相关产品推荐
相关产品推荐

