Laravel 9更新关联模型报错:SQLSTATE[42S22] 1054列不存在
解决Laravel关联模型批量更新时的字段不匹配问题
问题场景
在Laravel应用中,Employee模型与Salary、Title模型为一对多关联,需通过EmployeeController的updateEmployee方法同时更新三张表数据,但执行时出现以下错误:
Illuminate\Database\QueryException: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'first_name' in 'field list' (SQL: update
titlessetfirst_name= kevin,salary= 90000 wheretitles.emp_no= 10 andtitles.emp_nois not null)
错误原因
直接将$request->all()传入$employee->titles()->update()和$employee->salaries()->update(),但请求参数包含Employee模型的专属字段(如first_name),这些字段在Title和Salary表中不存在,导致SQL执行失败。同时原代码先执行关联模型更新、再判断员工是否存在,逻辑顺序错误。
解决方案
1. 配置模型可批量赋值字段
在对应模型中设置$fillable属性,明确允许批量更新的字段:
- Employee模型:
class Employee extends Model { protected $fillable = ['first_name', 'last_name', 'emp_no']; // 替换为实际业务字段 // 关联方法... }
- Title模型:
class Title extends Model { protected $fillable = ['title', 'from_date', 'to_date']; // 替换为实际业务字段 // 关联方法... }
- Salary模型:
class Salary extends Model { protected $fillable = ['salary', 'from_date', 'to_date']; // 替换为实际业务字段 // 关联方法... }
2. 修改控制器更新逻辑
调整updateEmployee方法,先校验员工存在性,再精准拆分请求参数更新对应模型,同时用事务保证数据一致性:
public function updateEmployee(Request $request, $id) { // 先校验员工是否存在 $employee = Employee::find($id); if (is_null($employee)) { return response()->json(['message' => 'Employee not found'], 404); } // 开启事务,确保多表更新原子性 \DB::beginTransaction(); try { // 更新Employee表 $employee->update($request->only(['first_name', 'last_name'])); // 更新关联的Title表 $employee->titles()->update($request->only(['title', 'from_date', 'to_date'])); // 更新关联的Salary表 $employee->salaries()->update($request->only(['salary', 'from_date', 'to_date'])); \DB::commit(); return response($employee, 200); } catch (\Exception $e) { \DB::rollBack(); return response()->json(['message' => 'Update failed', 'error' => $e->getMessage()], 500); } }
3. 核心优化点
- 用
$request->only()精准提取各模型的专属字段,避免无关字段传入导致SQL错误。 - 事务处理确保三张表要么同时更新成功,要么全部回滚,避免数据不一致。
- 先校验员工存在性,减少无效的关联模型更新操作。
内容的提问来源于stack exchange,提问作者Narakaya
相关产品推荐
相关产品推荐

