You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel仓库产品展示问题:移除->first()后traceability报错

问题分析

你遇到的核心问题是:

  • 使用->first()时,只会获取产品的单条库存记录,导致同一产品有多条库存时,仅能显示第一条库存信息,且产品基础信息重复
  • 移除->first()后,查询返回的是Collection集合对象,而非单个模型实例,直接访问->traceability这类属性会触发"试图获取非对象属性"的错误

同时原代码存在两次重复查询的冗余问题,还存在SQL注入风险(whereRaw直接拼接变量),一并优化。

解决方案

以下是优化后的代码,通过一次查询获取所有数据并按产品分组,然后遍历生成包含所有库存信息的HTML:

$Input = $request->key;
$almacen = $request->almacen;

// 一次查询获取所有符合条件的产品+库存数据,用参数绑定避免SQL注入
$productsWithInventories = DB::table('products')
    ->leftJoin('inventories', 'inventories.product_id', '=', 'products.id')
    ->leftJoin('warehouses', 'inventories.warehouse_id', '=', 'warehouses.id')
    ->where(function ($query) use ($Input) {
        $query->where('products.reference', 'like', "%{$Input}%")
              ->orWhere('products.name', 'like', "%{$Input}%");
    })
    ->where('warehouses.id', $almacen)
    ->whereNull('products.deleted_at')
    ->whereNull('inventories.deleted_at')
    ->select([
        'products.reference',
        'products.name',
        'products.sku',
        'products.id',
        'inventories.lot',
        'inventories.expirationDate',
        'inventories.traceability',
        'inventories.warehouse_id'
    ])
    ->get()
    // 按产品ID分组,把同一产品的所有库存记录归到一组
    ->groupBy('id');

$html = '';

// 判断是否有结果,用isEmpty()更严谨
if (!$productsWithInventories->isEmpty()) {
    foreach ($productsWithInventories as $productId => $inventoryItems) {
        // 取产品基础信息(同一组里的基础信息一致,取第一个即可)
        $productBase = $inventoryItems->first();
        
        // 遍历该产品的每条库存记录,生成HTML
        foreach ($inventoryItems as $item) {
            $html .= '<div>
                <a style="color: #000000" class="suggest-element" 
                   traceability="' . e($item->traceability) . '" 
                   reference="' . e($productBase->reference) . '" 
                   sku="' . e($productBase->sku) . '" 
                   name="' . e($productBase->name) . '" 
                   lot="' . e($item->lot) . '" 
                   expirationDate="' . e($item->expirationDate) . '" 
                   data="' . e($productBase->reference . ' ' . $productBase->name) . '" 
                   id="' . e($productBase->id) . '">
                    ' . e($productBase->reference) . ' ' . e($productBase->name) . ' ' . e($item->lot) . ' ' . e($item->expirationDate) . ' ' . e($item->traceability) . '
                </a>
            </div>';
        }
    }
} else {
    $html .= '<div><a style="color: #000000" class="suggest-element" exist="0" data="Sin coincidencias." id="0">Sin coincidencias.</a></div>';
}

return $html;
关键改动说明
  1. SQL注入防护:把原whereRaw的字符串拼接换成闭包内的参数绑定写法,避免恶意输入导致的注入风险
  2. 数据分组:用->groupBy('id')将同一产品的所有库存记录分组,避免产品基础信息重复处理
  3. 安全输出:用Laravel的e()函数对输出内容进行转义,防止XSS攻击
  4. 逻辑简化:移除冗余的第二次查询,直接基于第一次查询的结果生成HTML,提升性能
  5. 严谨判断:用isEmpty()替代字符串对比$name != '[]',更符合集合操作的规范

内容的提问来源于stack exchange,提问作者user20389386

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 09:31:42