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

Laravel中如何校验匹配数据并仅插入新数据?

问题:API数据插入时无法过滤已存在记录,重复插入所有数据

我从API获取商品数据,需要和数据库中ProductZoovu表的现有记录匹配,只插入新数据,但当前代码会插入所有数据,包括已存在的。以下是我的代码:

$retailer_id = ZoovuRetailer::where('name', $name)->first();

if ($retailer_id) {
    $get_api = ZoovuRetailerUrl::where('zoovu_retailer_id', $retailer_id->id)->first()->uri;
    $history = $retailer_id->setFeedStart(FeedHistory::TASK_ZOOVU);
    $client = new Client(['exceptions' => false]);
    $response = $client->request('GET', $get_api);

    if ($get_api) {
        try {
            $data = json_decode($response->getBody(), true);
            $brands = WcBrand::all()->pluck('brand_name')->toArray();

            $existing_products = ProductZoovu::where('zoovu_retailer_id', $retailer_id->id)
                ->pluck('offer_product_id')
                ->toArray();

            // Loop through the API data and insert new products
            foreach ($data as $item) {
                // Check if the brand is in the list of allowed brands
                if (in_array($item['brand'], $brands)) {
                    // Check if the product ID already exists in the database
                    if (!in_array($item['id'], $existing_products)) {
                        DB::beginTransaction();
                        try {
                            // Insert the new product
                            ProductZoovu::create([
                                'zoovu_retailer_id' => $retailer_id->id,
                                'model' => $item['variants'][0]['sku'],
                                'msrp' => round($item['variants'][0]['price'], 2),
                                'offer_url_en' => $item['url'],
                                'offer_product_id' => $item['id'],
                            ]);
                            DB::commit();
                        } catch (\Exception $exception) {
                            DB::rollback();
                            dd($exception);
                        }
                    }
                }
            }
        } catch (\Exception $exception) {
            $errorHandlingService = ErrorHandlingService::class;
            $errorHandlingService->handleRecordFeedHistory($exception, $history);
        }
        $retailer_id->setFeedEnd($history);
    }
}

排查与解决方案

1. 检查ID字段的数据类型匹配

数据库中offer_product_id字段的类型(如字符串/整数)与API返回的$item['id']类型可能不一致,导致in_array匹配失败。比如数据库存的是字符串,API返回的是整数,默认严格比较会判定为不相等。

可以强制统一类型:

// 将数据库查询到的ID转为字符串数组
$existing_products = ProductZoovu::where('zoovu_retailer_id', $retailer_id->id)
    ->pluck('offer_product_id')
    ->map(fn($id) => (string)$id)
    ->toArray();

// 循环中也将API返回的ID转为相同类型
$itemId = (string)$item['id'];
if (!in_array($itemId, $existing_products)) {
    // 插入逻辑
}

2. 确认API返回的ID字段正确性

检查API返回的$item['id']是否为商品的唯一标识,是否存在字段名错误(比如应该用$item['product_id'])。可以用dd($data)打印API返回的完整结构,确认唯一ID的键名。

3. 验证existing_products的查询结果

确认ProductZoovu::where('zoovu_retailer_id', $retailer_id->id)是否正确过滤了当前零售商的商品。比如是否字段名写错(如zoovu_retailer_id应为retailer_id),或者$retailer_id->id的值不正确。可以用dd($existing_products)查看查询结果,是否包含已存在的商品ID。

4. 排查品牌过滤逻辑的干扰

品牌名可能存在大小写、空格差异(比如API返回"Nike",而$brands里是"nike"),导致品牌过滤失效,所有商品都进入插入逻辑。可以统一转为小写后再比较:

$brands = WcBrand::all()->pluck('brand_name')->map(fn($b) => strtolower($b))->toArray();
// 循环中
if (in_array(strtolower($item['brand']), $brands)) {
    // ...
}

5. 改用数据库层面的唯一约束与firstOrCreate

为彻底避免重复插入,建议给ProductZoovu表添加(zoovu_retailer_id, offer_product_id)联合唯一索引,同时用Laravel的firstOrCreate方法简化逻辑,该方法会自动处理查询与插入,比手动数组检查更可靠:

// 循环中替换原有的插入逻辑
ProductZoovu::firstOrCreate(
    // 查询条件:唯一标识组合
    ['zoovu_retailer_id' => $retailer_id->id, 'offer_product_id' => $item['id']],
    // 新记录的其他字段
    [
        'model' => $item['variants'][0]['sku'],
        'msrp' => round($item['variants'][0]['price'], 2),
        'offer_url_en' => $item['url'],
    ]
);

这种方式无需手动查询existing_products,还能避免并发场景下的重复插入问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 19:44:54