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

使用Guzzle HTTP Client多API请求时,json_decode返回首个请求结果问题

问题排查与解决方案

核心原因猜测

你遇到的问题大概率出自两个方向:要么是$baseApiCall->sendRequest的封装方法存在复用响应的bug,要么是Guzzle响应体的流读取逻辑没处理对——Guzzle的响应体是流式对象,调用getContents()后指针会移到流末尾,若复用流对象或未重置指针,会导致读取到旧内容。

分步解决方法

1. 先确认第二个请求的真实响应

在解析前直接打印响应内容,验证是否真的返回了第一个请求的结果:

$receiptsResponse = $baseApiCall->sendRequest('GET', $receiptsApiUrl);
// 打印状态码和原始响应体,确认请求结果
var_dump($receiptsResponse->getStatusCode());
echo $receiptsResponse->getBody()->getContents();
// 重置流指针,避免后续读取为空
$receiptsResponse->getBody()->rewind();

如果打印内容确实是第一个请求的结果,直接检查$baseApiCall的sendRequest实现——大概率是这个封装方法没有正确发起新请求,而是缓存/复用了第一次的响应对象。

2. 修复Guzzle响应体读取逻辑

如果sendRequest没问题,那是流读取的问题,改用Guzzle内置的json()方法直接解析,它会自动处理流的读取和重置:

if ($receiptsResponse->getStatusCode() == 200) {
    // 替换手动json_decode,用内置方法直接解析JSON
    $receiptsData = $receiptsResponse->json();
}

如果一定要手动读取,记得每次读取前重置流指针:

$body = $receiptsResponse->getBody();
$body->rewind(); // 重置到流的开头
$receiptsData = json_decode($body->getContents(), true);

3. 检查$baseApiCall的封装逻辑

打开$baseApiCall对应的类,确认sendRequest方法每次都创建了新的HTTP请求:

  • 确保没有将响应对象存在类属性中重复返回
  • 确认Guzzle客户端的调用是每次都发起新请求,没有错误启用缓存中间件
  • 检查是否有逻辑错误导致请求URL被覆盖或复用

4. 修复URL拼接的安全问题

顺便提醒:直接把变量拼到URL查询参数里存在注入风险,建议用参数化方式构建查询:

$receiptsApiUrl = "<api URL I am using>/purchaseReceipts";
$query = [
    '$filter' => "orderNumber eq '$orderNumber'",
    '$expand' => "purchaseReceiptLines(\$filter=lineObjectNumber eq '$lineObjectNumber')"
];
// 若sendRequest支持传入查询参数则直接传入;原生Guzzle可这么调用:
$receiptsResponse = $client->request('GET', $receiptsApiUrl, ['query' => $query]);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 15:01:26