Laravel关联查询报错:Attempt to read property on null求助
一、员工分类关联空指针错误
错误信息
Attempt to read property "id" on null (View: C:\xampp\htdocs\resources\views\admin\employees\show.blade.php)
相关代码
show.blade.php:
'Category' => '<a href="'. route('admin.employee-categories.show', $model->category->id) . '">' . $model->category->name . '</a>',
Employee模型:
public function category(): BelongsTo { return $this->belongsTo(EmployeeCategory::class, 'category_id'); }
尝试修改后的问题
修改代码:
'Category' => '<a href="'. route('admin.employee-categories.show', $model->category ? $model->category->id: '') . '">' . $model->category ? $model->category->name : ' ' . '</a>',
触发新错误:Attempt to read property "name" on null (View: C:\xampp\htdocs\resources\views\admin\employees\show.blade.php)
二、软删除员工后证书列表页空指针错误
错误信息
Attempt to read property "name" on null (View: C:\xampp\htdocs\resources\views\components\data-table.blade.php)
触发场景
在员工列表页软删除一名员工后,进入员工证书列表页,未显示员工已删除状态,反而抛出上述错误。
相关代码
EmployeeCertificates/index.blade.php:
[ 'attribute' => function($item) { return $item->employee->name; }, 'label' => 'Сотрудник', 'style' => 'width: 30%; min-width: 200px;', 'filter' => [ 'class' => \App\View\Components\Filters\Select::class, 'params' => [ 'name' => 'employee_id', 'options' => $employees->pluck('name', 'id')->toArray(), 'value' => request()->get('employee_id', ''), 'htmlAttributes' => '', ], ], ],
Employee模型:
public function certificates(): HasMany { return $this->hasMany(EmployeeCertificate::class, 'employee_id'); }
解决方法
1. 修复员工分类关联问题
你之前的修改失败是因为运算符优先级:三元运算符?:优先级低于字符串拼接,导致$model->category先和前面的字符串拼接,再执行判断,最终仍会在category为空时读取name属性。
推荐使用Laravel的可选链运算符?->和空合并运算符??,同时给三元表达式加括号保证优先级:
'Category' => '<a href="'. route('admin.employee-categories.show', $model->category?->id ?? '') . '">' . ($model->category?->name ?? '无分类') . '</a>',
$model->category?->id:若category为null,直接返回null,不会触发错误?? '':避免route函数因参数为null报错($model->category?->name ?? '无分类'):确保空值时显示默认文本,括号保证运算顺序正确
2. 修复软删除员工的证书关联问题
软删除的员工默认不会被关联查询返回,因此$item->employee为null,直接读取name会报错,有两种解决方式:
方式一:视图层做空值判断
用可选链和空合并运算符快速处理:
'attribute' => function($item) { return $item->employee?->name ?? '已删除员工'; },
方式二:关联查询包含软删除数据
在EmployeeCertificate模型中修改关联定义,加入withTrashed():
public function employee(): BelongsTo { return $this->belongsTo(Employee::class, 'employee_id')->withTrashed(); }
之后可以进一步判断员工是否被软删除,显示对应状态:
'attribute' => function($item) { return $item->employee ? ($item->employee->trashed() ? '已删除员工' : $item->employee->name) : '无关联员工'; },
3. 预防措施
- 数据库层面:如果
category_id是必填字段,添加非空约束和外键关联,从根源避免关联为空的情况。 - 查询层面:查询员工数据时用
with('category')预加载关联,若业务需要,可通过whereHas('category')过滤掉无分类的员工。 - 软删除场景:涉及关联软删除模型时,根据业务需求选择是否用
withTrashed()包含软删除数据,或在视图层统一做空值判断。
内容的提问来源于stack exchange,提问作者aleksandr134

