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

PHP7.4循环调用API时isset判断引发504超时与空数组偏移问题求助

根因说明

你遇到的超时和isset函数本身完全无关,isset是PHP内核实现的轻量判断函数,不可能引发超时。真正的问题是你的循环逻辑存在严重的重复API调用问题:

  • 你在while遍历每一条数据库返回行的内部,额外加了一层foreach ($row as $key => $value)遍历当前行的所有字段。只要某一轮遍历中$sudCode和$sudBroj被赋值后,后续遍历其他字段时这两个变量依旧保留有效值,会重复触发ePredmetiAPI调用,相当于一行数据你调用了N次API(N为行字段数),数据量上来后必然会因为API调用次数过多导致超时。
  • 你移除isset判断后脚本能跑完,只是因为少了后续的逻辑处理,执行速度变快刚好没触发Apache超时阈值,本质问题并没有解决。

可行解决方案

步骤1:修复UNION查询,统一字段别名

UNION查询的结果集字段名由第一个查询决定,给字段加统一别名避免后续取值混乱:

$results = mysqli_query($con, "
    SELECT DISTINCT 
        predf_nas_br as nas_br, 
        predf_odv as odv,  
        predf_SUD as sud, 
        predf_SUDBROJ as sud_broj
    FROM PREDMETIFView 
    WHERE predf_SUD <> '' AND predf_SUDBROJ <> '' AND predf_SUDBROJ NOT LIKE '% %'
    UNION ALL   
    SELECT DISTINCT 
        predp_nas_br as nas_br, 
        predp_odv as odv,  
        predp_SUD as sud, 
        predp_SUDBROJ as sud_broj
    FROM PREDMETIPView 
    WHERE predp_SUD <> '' AND predp_SUDBROJ <> '' AND predp_SUDBROJ NOT LIKE '% %'
;");

步骤2:预生成sud映射表,删除低效遍历查询

原来的findSudCode每次调用都要遍历整个数组,预转成键值对映射表后可以O(1)取值:

// 原eSudovi()函数保持不变,处理返回结果时转映射表
$eSudovi = eSudovi()["data"]["sudovi"] ?? [];
$sudoviMap = [];
foreach ($eSudovi as $item) {
    $sudoviMap[trim($item['sudNaziv'])] = $item['id'];
}

步骤3:给CURL加超时配置,避免单请求阻塞

在eSudovi()和ePredmeti()两个函数的CURL配置段添加超时规则:

curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); // 连接超时5秒
curl_setopt($ch, CURLOPT_TIMEOUT, 10); // 整个请求最多等待10秒

步骤4:重写核心循环,删除多余字段遍历

彻底去掉内层的foreach ($row as $key => $value),一行数据仅调用一次API:

while ($row = $results->fetch_assoc()) {
    $nas = $row['nas_br'] ?? '';
    $sud = trim($row['sud'] ?? '');
    $sudBroj = trim($row['sud_broj'] ?? '');
    $sudCode = $sudoviMap[$sud] ?? null;

    // 无效参数直接跳过
    if (empty($sudCode) || empty($sudBroj)) {
        continue;
    }

    $epredmet = ePredmeti($sudCode, $sudBroj);
    // 仅匹配lastUpdateTime为有效字符串的第三种场景
    if (!empty($epredmet['data']['prvi']['lastUpdateTime']) && is_string($epredmet['data']['prvi']['lastUpdateTime'])) {
        $lastUpdateTime = $epredmet["data"]["prvi"]["lastUpdateTime"];
        $dateTime  = str_replace("T", " ", $lastUpdateTime);
        echo $nas . " - " . $dateTime . "<br>";
    }
}

额外优化建议

如果数据量较大,可以给API调用增加本地缓存,相同$sudCode + $sudBroj的请求不用重复调用接口,进一步减少请求量。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.14 14:06:03