Laravel DB查询报Trying to get property 'id' of non-object错误排查
问题根因
触发Trying to get property 'id' of non-object报错的直接原因是:遍历全量产品时,存在部分产品没有匹配到is_xml=1的变体价格记录。
查询构造器的first()方法在找不到匹配数据时会返回null,此时直接访问$vprice->id本质是在访问null值的属性,必然触发非对象错误。你之前调试时能拿到正常返回结果,是因为dd()会在第一次命中有效结果的循环轮次直接终止程序,没有执行到后续无匹配数据的产品遍历逻辑,所以没复现报错。
修复方案
基础修复:增加判空逻辑
最直接的改法是在访问属性前先判断查询结果是否为空,同时可以在查询时指定只拉取需要的id、price字段,减少不必要的数据传输:
$products = Product::all(); foreach($products as $pr){ $vprice = DB::table('product_variation_prices') ->select('id', 'price') ->where('product_id', $pr->id) ->where('is_xml', 1) ->first(); // 无匹配记录时跳过当前产品的后续逻辑 if (is_null($vprice)) { // 如需排查脏数据,可以在这里打印对应产品ID // dump("产品ID:{$pr->id} 无匹配的xml变体价格"); continue; } // 此处可安全访问属性 $variationId = $vprice->id; $variationPrice = $vprice->price; // 编写后续业务逻辑 }
性能优化:避免N+1查询问题
你当前循环内反复查库的写法属于典型的N+1查询问题,产品量级上来后会产生大量数据库请求,拖慢接口性能,可以用一次查询拉取所有需要的变体数据再分组匹配:
// 一次性拉取所有符合条件的变体价格,按产品ID分组 $variationPrices = DB::table('product_variation_prices') ->select('id', 'price', 'product_id') ->where('is_xml', 1) ->whereIn('product_id', Product::pluck('id')) ->get() ->groupBy('product_id'); $products = Product::all(); foreach($products as $pr){ // 从内存已拉取的集合中匹配数据,无需重复查库 $vprice = $variationPrices->get($pr->id)?->first(); if (is_null($vprice)) { continue; } // 后续正常使用$vprice->id、$vprice->price即可 }
注:上述代码中的
?->是PHP8.0及以上版本支持的空安全操作符,若项目运行在PHP7.x环境,将对应取值逻辑替换为isset($variationPrices[$pr->id]) ? $variationPrices[$pr->id]->first() : null即可兼容。
内容的提问来源于stack exchange,提问作者Ontrable
相关产品推荐
相关产品推荐

