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

PHP中如何基于一个API响应在foreach循环内调用另一个API?

基于curl_multi的API批量调用与数据入库实现模板

以下是适配你场景的PHP通用实现方案,解决串行调用API效率低、执行无法结束的问题,同时规范数据入库流程:

核心流程

  1. 调用第一个API获取目标ID数组
  2. 利用curl_multi并发调用第二个API(每个ID对应一个请求)
  3. 合并两个API的响应数据
  4. 批量插入MySQL数据库

完整代码实现

<?php
// -------------------------- 配置区 --------------------------
// 第一个API地址(获取ID数组)
$firstApiUrl = 'https://example.com/api/get-ids';
// 第二个API地址模板({id}为占位符)
$secondApiTemplate = 'https://example.com/api/get-detail/{id}';
// MySQL数据库配置
$dbConfig = [
    'host' => 'localhost',
    'dbname' => 'your_database',
    'user' => 'your_user',
    'password' => 'your_password'
];
// curl并发请求的批次大小(避免一次性创建过多请求导致资源耗尽)
$batchSize = 10;

// -------------------------- 第一步:获取ID数组 --------------------------
$ch = curl_init($firstApiUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10); // 设置超时防止无限等待
$idResponse = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

// 处理第一个API的响应
if ($httpCode !== 200 || empty($idResponse)) {
    die('Failed to fetch ID array from first API');
}
$idArray = json_decode($idResponse, true);
// 校验ID数组格式(根据实际API返回结构调整)
if (!is_array($idArray) || empty($idArray)) {
    die('Invalid ID array format');
}

// -------------------------- 第二步:curl_multi批量调用第二个API --------------------------
$detailData = [];
// 分批处理ID,避免并发数过大
$idBatches = array_chunk($idArray, $batchSize);

foreach ($idBatches as $batch) {
    $mh = curl_multi_init();
    $curlHandles = [];

    // 为每个ID创建curl handle并加入multi批处理
    foreach ($batch as $id) {
        $apiUrl = str_replace('{id}', $id, $secondApiTemplate);
        $ch = curl_init($apiUrl);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 8);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        $curlHandles[$id] = $ch;
        curl_multi_add_handle($mh, $ch);
    }

    // 执行批量请求
    $running = null;
    do {
        curl_multi_exec($mh, $running);
        curl_multi_select($mh); // 等待请求完成,减少CPU占用
    } while ($running > 0);

    // 收集每个请求的响应
    foreach ($curlHandles as $id => $ch) {
        $response = curl_multi_getcontent($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        
        if ($httpCode === 200 && !empty($response)) {
            $detail = json_decode($response, true);
            // 合并ID与详情数据(根据实际需求调整字段)
            $detailData[] = [
                'source_id' => $id,
                'detail_data' => json_encode($detail), // 若需存储结构化数据,可存JSON
                // 可额外添加第一个API的关联字段(如果有)
            ];
        } else {
            // 记录错误日志(生产环境建议写入日志文件)
            error_log("Failed to fetch detail for ID {$id}, HTTP code: {$httpCode}");
        }
        // 释放单个curl handle
        curl_multi_remove_handle($mh, $ch);
        curl_close($ch);
    }
    // 释放multi handle
    curl_multi_close($mh);
}

// -------------------------- 第三步:批量插入MySQL --------------------------
if (empty($detailData)) {
    die('No valid data to insert');
}

try {
    $pdo = new PDO(
        "mysql:host={$dbConfig['host']};dbname={$dbConfig['dbname']};charset=utf8mb4",
        $dbConfig['user'],
        $dbConfig['password'],
        [
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
        ]
    );

    // 预处理插入语句(根据你的表结构调整字段)
    $insertSql = "INSERT INTO your_table (source_id, detail_data, created_at) VALUES (?, ?, NOW())";
    $stmt = $pdo->prepare($insertSql);

    // 开启事务提升插入效率
    $pdo->beginTransaction();
    foreach ($detailData as $data) {
        $stmt->execute([
            $data['source_id'],
            $data['detail_data']
        ]);
    }
    $pdo->commit();
    echo 'Data inserted successfully. Total rows: ' . count($detailData);
} catch (PDOException $e) {
    $pdo->rollBack();
    die('Database error: ' . $e->getMessage());
}
?>

关键说明

  • curl_multi优势:替代串行foreach的curl调用,通过并发请求大幅减少总耗时,同时避免单个请求阻塞导致程序无法结束
  • 批次处理:设置$batchSize控制并发数,防止一次性创建过多curl连接耗尽服务器资源
  • 超时控制:为每个curl请求设置CURLOPT_TIMEOUT,避免请求挂起导致程序僵死
  • 数据库安全:使用PDO预处理语句防止SQL注入,开启事务保证数据一致性
  • 错误处理:针对API请求失败、数据库异常做了基础捕获,生产环境建议扩展日志记录逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 22:40:32