一对多关联中父模型无子模型时触发非对象错误求助
问题分析与解决方案
错误原因
当服务器没有对应的server_status记录时,$server->serverStatus会返回一个空的Collection,调用->last()方法后得到的是null。此时你尝试访问null->status_id,就会触发“Trying to get property 'status_id' of non-object”的错误——因为null不是对象,根本无法读取它的属性。你之前写的elseif($server->serverStatus->last()->status_id === null)永远不会被执行,因为在执行到这行代码之前就已经报错中断了。
解决方案
我们可以通过两种方式避免这个错误:提前检查状态记录是否存在,或者使用Laravel提供的optional()辅助函数来安全访问属性。
方案1:先获取最新状态并检查是否存在
在模板里先把最新的状态记录存到变量里,再判断是否存在,之后再访问status_id:
@php $latestStatus = $server->serverStatus->last(); @endphp @if($latestStatus && $latestStatus->status_id === 1) <a href="/servers/{{$server->id}}" class="text-dark list-group-item list-group-item-success">{{$server->name}}</a> @elseif($latestStatus && $latestStatus->status_id === 2) <a href="/servers/{{$server->id}}" class="text-dark list-group-item list-group-item-warning">{{$server->name}}</a> @elseif($latestStatus && $latestStatus->status_id === 3) <a href="/servers/{{$server->id}}" class="text-dark list-group-item list-group-item-danger">{{$server->name}}</a> @elseif($latestStatus && $latestStatus->status_id === 4) <a href="/servers/{{$server->id}}" class="text-dark list-group-item list-group-item-warning">{{$server->name}} is under maintenance</a> @else <a href="/servers/{{$server->id}}" class="text-dark list-group-item list-group-item-warning">{{$server->name}} has no inputted status</a> @endif
方案2:使用optional()辅助函数
Laravel的optional()函数可以安全地访问对象属性,如果传入的是null,它会返回null而不是抛出错误:
@if(optional($server->serverStatus->last())->status_id === 1) <a href="/servers/{{$server->id}}" class="text-dark list-group-item list-group-item-success">{{$server->name}}</a> @elseif(optional($server->serverStatus->last())->status_id === 2) <a href="/servers/{{$server->id}}" class="text-dark list-group-item list-group-item-warning">{{$server->name}}</a> @elseif(optional($server->serverStatus->last())->status_id === 3) <a href="/servers/{{$server->id}}" class="text-dark list-group-item list-group-item-danger">{{$server->name}}</a> @elseif(optional($server->serverStatus->last())->status_id === 4) <a href="/servers/{{$server->id}}" class="text-dark list-group-item list-group-item-warning">{{$server->name}} is under maintenance</a> @else <a href="/servers/{{$server->id}}" class="text-dark list-group-item list-group-item-warning">{{$server->name}} has no inputted status</a> @endif
额外优化:预加载关联避免N+1查询
另外,建议在控制器里预加载serverStatus关联,这样可以避免执行大量重复的查询,提升页面性能:
public function index(){ // 使用with()预加载关联 $servers = Server::with('serverStatus')->orderBy('created_at', 'desc')->get(); $incidents = Incident::orderBy('created_at', 'desc')->paginate(10); return view('pages.index', ['incidents' => $incidents, 'servers' => $servers]); }
内容的提问来源于stack exchange,提问作者Striker
相关产品推荐
相关产品推荐

