Laravel Blade视图获取非对象属性报错原因咨询
嘿,这个问题我之前也踩过坑,咱们一步步来捋清楚为啥会出现这个错误:
首先,报错「Trying to get property of non-object」的核心原因是:某些UploadsPois实例根本找不到符合条件的Log记录,导致first()返回了null,你直接去访问null的comentario属性,自然就炸了。
那为啥直接输出{{$carga->Log()->first()}}看起来正常呢?这是因为Laravel的Blade模板引擎会自动处理null这类空值,不会强制输出,所以页面上不会报错,但实际上这个表达式的结果就是null,只是Blade帮你“遮”过去了。
再给你拆解两个关键细节:
1. 别搞混关联的调用方式:Log() vs Log
你在Blade里写的$carga->Log()是带括号的方法调用,这其实会重新发起一次数据库查询,而不是用你在with()里预加载好的数据!虽然查询条件和预加载的一致,但这种写法会多跑不必要的DB请求,而且一旦某个UploadsPois没符合条件的Log,first()就返回null。
如果想用预加载的缓存数据,应该用属性形式的$carga->Log(不带括号),直接用已经加载到模型里的集合,不用再查数据库。
2. 部分UploadsPois的Log集合是空的
看你预加载Log时的查询条件:
$log->where('schema_country', $schema_country) ->whereNull('address_id') ->orderBy('id', 'desc');
这个查询是捞所有符合这两个条件的Log,但有些UploadsPois可能压根没有满足这些条件的Log记录,所以它的Log关联集合就是空的。这时候不管你用$carga->Log()->first()还是$carga->Log->first(),得到的都是null,直接访问comentario肯定报错。
给你几个简单可行的方案,按需选:
方案一:用可选链运算符(PHP 8.0+推荐)
这是最简洁的写法,只要first()返回null,就会自动返回空,不会报错:
{{ $carga->Log->first()?->comentario }}
(这里用不带括号的Log属性,用预加载的数据,省DB请求)
方案二:用optional()辅助函数(兼容低版本PHP)
如果你的项目PHP版本低于8.0,用Laravel自带的optional()函数包装一下就行:
{{ optional($carga->Log->first())->comentario }}
方案三:先判断再输出
用条件语句先检查有没有Log记录,再输出属性,看起来更直观:
@if($log = $carga->Log->first()) {{ $log->comentario }} @endif
额外优化:预加载时直接只取第一条Log
如果你业务里本来就只需要每个UploadsPois的最新一条Log,完全可以在预加载的时候就限制只取第一条,省得在Blade里再调用first():
// 修改Eloquent查询里的Log预加载逻辑 'Log' => function ($log) use ($schema_country) { $log->where('schema_country', $schema_country) ->whereNull('address_id') ->orderBy('id', 'desc') ->limit(1); // 只捞第一条 }
之后在Blade里就可以直接这么写:
{{ $carga->Log->first()?->comentario }}
内容的提问来源于stack exchange,提问作者pmiranda

