使用curl_multi获取数据后无法访问数组偏移量的问题排查
问题
使用curl_multi批量请求API时,尝试通过$results[2]['context']或$results[0]['dom']访问数据,出现「Cannot access offset of type string on string」或「Undefined array key」错误,无法直接或循环访问结果,怀疑是curl_multi使用方式导致数组异常。
我的代码:
<?php session_start(); $authorization = "Authorization: Bearer ".$_SESSION['toke']; $domurl = 'https://api.xxxx.xx/intel/v4/dom/' . $_POST['domata']; $dimurl = 'https://api.xxxx.xx/intel/v4/dom/' . $_POST['domata'] . '/dim'; $conurl = 'https://api.xxxx.xx/intel/v4/dom/' . $_POST['domata'] . '/con'; $lisurl = 'https://api.xxxx.xx/intel/v4/dom/' . $_POST['domata'] . '/lis'; $senurl = 'https://api.xxxx.xx/intel/v4/dom/' . $_POST['domata'] . '/sen'; $nsurl = 'https://api.xxxx.xx/intel/v4/dom/' . $_POST['domata'] . '/ns'; $malurl = 'https://api.xxxx.xx/intel/v4/dom/' . $_POST['domata'] . '/mal/urls'; $requests = array($domurl, $dimurl, $conurl, $lisurl, $senurl, $nsurl, $malurl); $main = curl_multi_init(); $results = array(); $errors = array(); $info = array(); $count = count($requests); for($i = 0; $i < $count; $i++) { $handles[$i] = curl_init($requests[$i]); //var_dump($requests[$i]); curl_setopt_array($handles[$i], array( CURLOPT_URL => $requests[$i], CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 0, CURLOPT_FOLLOWLOCATION => true, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => 'GET', CURLOPT_HTTPHEADER => array($authorization), )); //curl_setopt($handles[$i], CURLOPT_URL, $requests[$i]); //curl_setopt($handles[$i], CURLOPT_RETURNTRANSFER, 1); curl_multi_add_handle($main, $handles[$i]); } $running = 0; do { curl_multi_exec($main, $running); } while($running > 0); for($i = 0; $i < $count; $i++) { $results[] = curl_multi_getcontent($handles[$i]); //$errors[] = curl_error($handles[$i]); //$info[] = curl_getinfo($handles[$i]); curl_multi_remove_handle($main, $handles[$i]); } curl_multi_close($main); //print_r($results); //echo implode(" ",$results); //echo json_encode($results); var_dump($results); //var_dump($errors); echo $requests[0]. " ==><br>"; //echo gettype($results); //print_r($info[0]); echo "<br><br>"; echo '<table class="tftable" border="1">'; //if (isset($results['dom'])){ //$domm = $results['dom']; //echo 'Dom: ' . $domm; } print_r(array_values($results)); print("<pre>".print_r($results,true)."</pre>"); echo ' <tr>'; echo ' <th colspan=4><center>Dom Info</th></center>'; echo ' </tr>'; echo ' <tr><th>Type</th><th>Value</th><th>Laseen</th></tr>'; echo ' <td>Dom: </td>'; echo ' <td> ' . $results['2']['context'] . '</td> '; echo ' <td>' . date('m/d/Y H:i', $results['lseen']) . '</td>'; echo ' </tr>'; //print_r(); ?>
输出结果:
Array ( [0] => {"dom":"biggie.com","lseen":9393789,"ebused":false,"who":{"created":7416583,"expire":7032583,"reg":"Company Solutions, LLC"},"score":144.5} [1] => {"human-test":12.5,"infrared":12} [2] => [{"context":"cert","lseen":393789},{"context":"hello","last-seen":9361558},{"context":"mailbody","lseen":545360},{"context":"sample","lseen":1645360}] [3] => {"ts":9393789,"listed":false} [4] => [{"ip":"314.199.23.133","hello":"biggie.com","lseen":167558,"score":49.6},{"ip":"629.732.363.252","hello":null,"lseen":167360,"score":15.5},{"ip":"49.75.156.214","hello":null,"lseen":167785,"score":191.1}] [5] => [{"ns":"graham.ns.asample.com","lseen":163789,"score":443.0003716,"counting":75},{"ns":"island.ns.potato.com","lseen":13789,"score":333.84,"counting":69}] [6] => [] )
Array ( [0] => {"dom":"biggie.com","lseen":9393789,"ebused":false,"who":{"created":7416583,"expire":7032583,"reg":"Company Solutions, LLC"},"score":144.5} [1] => {"human-test":12.5,"infrared":12} [2] => [{"context":"cert","lseen":393789},{"context":"hello","last-seen":9361558},{"context":"mailbody","lseen":545360},{"context":"sample","lseen":1645360}] [3] => {"ts":9393789,"listed":false} [4] => [{"ip":"314.199.23.133","hello":"biggie.com","lseen":167558,"score":49.6},{"ip":"629.732.363.252","hello":null,"lseen":167360,"score":15.5},{"ip":"49.75.156.214","hello":null,"lseen":167785,"score":191.1}] [5] => [{"ns":"graham.ns.asample.com","lseen":163789,"score":443.0003716,"counting":75},{"ns":"island.ns.potato.com","lseen":13789,"score":333.84,"counting":69}] [6] => [] )
解决方案
核心问题
当前$results数组存储的是JSON格式的字符串,并非PHP可直接访问的数组/对象。curl_multi_getcontent()返回的是API响应的原始文本,必须先解析为PHP数组才能通过键名访问数据。
修复步骤
- 解析JSON字符串:在存储结果时,使用
json_decode()将每个响应字符串转换为关联数组(第二个参数传true),同时处理解析失败的情况。 - 修正访问语法:数组索引需使用数字(如
$results[2]而非$results['2']),并匹配正确的数据层级。
修改后的关键代码
替换结果存储的循环部分:
for($i = 0; $i < $count; $i++) { // 获取原始响应并解析为关联数组,解析失败时返回空数组兜底 $response = curl_multi_getcontent($handles[$i]); $results[] = json_decode($response, true) ?: []; // 可选:记录请求错误和状态信息 $errors[] = curl_error($handles[$i]); $info[] = curl_getinfo($handles[$i]); curl_multi_remove_handle($main, $handles[$i]); }
正确访问示例
- 获取第一个请求的域名:
echo $results[0]['dom']; // 输出:biggie.com - 遍历第三个请求的context列表:
foreach($results[2] as $item) { $lastSeen = $item['lseen'] ?? $item['last-seen']; echo "Context: {$item['context']}, Last Seen: " . date('m/d/Y H:i', $lastSeen) . "<br>"; } - 修正表格部分的错误代码:
echo '<table class="tftable" border="1">'; echo ' <tr>'; echo ' <th colspan=3><center>Dom Info</th></center>'; echo ' </tr>'; echo ' <tr><th>Type</th><th>Value</th><th>Last Seen</th></tr>'; echo ' <td>Dom: </td>'; echo ' <td> ' . $results[0]['dom'] . '</td> '; echo ' <td>' . date('m/d/Y H:i', $results[0]['lseen']) . '</td>'; echo ' </tr>'; // 输出Context列表 echo '<tr><th colspan=3><center>Context List</th></center></tr>'; foreach($results[2] as $ctx) { $lastSeen = $ctx['lseen'] ?? $ctx['last-seen']; echo '<tr>'; echo '<td>Context</td>'; echo '<td>' . $ctx['context'] . '</td>'; echo '<td>' . date('m/d/Y H:i', $lastSeen) . '</td>'; echo '</tr>'; } echo '</table>';
额外注意事项
- 处理解析失败:
json_decode()在遇到非JSON格式内容时会返回null,用?: []兜底为空数组可避免后续访问报错。 - 验证请求状态:通过
$info[$i]['http_code']检查HTTP状态码(如200表示请求成功),再决定是否解析响应内容。
内容的提问来源于stack exchange,提问作者longtimelistener1sttimecaller
相关产品推荐
相关产品推荐

