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

Laravel 10关联数据插入:已知源名称获取外键ID的实现方案

问题:Laravel 10中通过源名称获取ID批量插入数据

我需要在Laravel 10中插入数据,外键source_id为int类型(示例值:2),但Python爬虫程序只能传入源名称(示例值:facebook.com),无法每次调用API获取源ID。源表数据场景如下:

  • 1: google.com
  • 2: facebook.com

现有模型代码(PropertyVault模型)

public function propertySource(): HasMany
{
    return $this->hasMany(PropertySource::class);
}

public function propertyNetworkPost(): HasMany{
    return $this->hasMany(PropertyNetworkPost::class);
}

现有控制器代码

public function storeUrl(Request $request){
    if(!$request->ad_urls){
        return response()->json([
            'status'=>'failed',
            'notification'=>__('Tidak ada input')
        ]);
    }

    ///解码嵌套JSON
    $ad_urls = $request->ad_urls ?? [];
    if(!is_array($ad_urls)){
        $ad_urls = json_decode($request->ad_urls,true);
    }

    ///创建批量插入数组
    $input = [];
    foreach($ad_urls as $item){
        $input [] = [
            'country' => $request->country,
            'source_id' => $request->source, // 此处为问题点:已知名称需获取对应ID
            'ad_url' => $item,
        ];
    }

    try{
        ///存在重复则忽略,并获取受影响行数
        $rows = PropertyVault::insertOrIgnore($input);
        if(empty($rows)){
            throw new PropertyException(message: 'no url to insert');
        }
    }
    catch(Exception $e){
        throw new PropertyException(message: $e->getMessage());
    }
    return response()->json([
        'status' => 'success',
        'message' => __("Inserting {$rows} urls"),
    ]);
}

尝试过的代码(存在问题:插入到父模型)

$propertySource = PropertySource::where('name',$request->source)->first();

$status = $propertySource->propertyVault()->create([
    'country' => 'ID',
    'source_id' => 1,
    'ad_url' => 'https://google'.rand(0,1999).'.com',
]);

解决方案

1. 修正关联关系

首先在PropertySource模型中添加与PropertyVault的关联(确保外键指向正确):

use Illuminate\Database\Eloquent\Relations\HasMany;

class PropertySource extends Model
{
    // ... 其他模型代码

    public function propertyVaults(): HasMany
    {
        return $this->hasMany(PropertyVault::class, 'source_id');
    }
}

2. 修改控制器逻辑

先根据传入的源名称查询对应的ID,再批量插入数据,同时增加源名称存在性校验:

public function storeUrl(Request $request)
{
    if (!$request->ad_urls) {
        return response()->json([
            'status' => 'failed',
            'notification' => __('Tidak ada input')
        ]);
    }

    // 校验源名称是否存在,避免插入无效外键
    $propertySource = PropertySource::where('name', $request->source)->first();
    if (!$propertySource) {
        return response()->json([
            'status' => 'failed',
            'notification' => __('源名称不存在')
        ]);
    }
    $sourceId = $propertySource->id;

    // 解码嵌套JSON
    $ad_urls = $request->ad_urls ?? [];
    if (!is_array($ad_urls)) {
        $ad_urls = json_decode($request->ad_urls, true);
    }

    // 构建批量插入数组
    $input = [];
    foreach ($ad_urls as $item) {
        $input[] = [
            'country' => $request->country,
            'source_id' => $sourceId, // 使用查询到的合法ID
            'ad_url' => $item,
        ];
    }

    try {
        // 存在重复则忽略,获取受影响行数
        $rows = PropertyVault::insertOrIgnore($input);
        if (empty($rows)) {
            throw new PropertyException(message: 'no url to insert');
        }
    } catch (Exception $e) {
        throw new PropertyException(message: $e->getMessage());
    }

    return response()->json([
        'status' => 'success',
        'message' => __("Inserting {$rows} urls"),
    ]);
}

3. 可选优化:缓存源映射

如果源数据不频繁更新,可以缓存名称与ID的映射,减少数据库查询次数:

// 从缓存获取,不存在则查询数据库并缓存
$sourceId = Cache::remember("source_id_{$request->source}", 3600, function () use ($request) {
    $source = PropertySource::where('name', $request->source)->value('id');
    if (!$source) {
        abort(400, '源名称不存在');
    }
    return $source;
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 16:15:12