
在使用Guzzle发送HTTP请求时,若对$response->getBody()返回的PSR-7 Stream对象误调用getStatusCode(),将触发“Call to undefined method”错误;正确做法是始终从ResponseInterface实例(即原始响应对象)获取状态码,而非从其body流中获取。
在使用guzzle发送http请求时,若对`$response->getbody()`返回的psr-7 stream对象误调用`getstatuscode()`,将触发“call to undefined method”错误;正确做法是始终从`responseinterface`实例(即原始响应对象)获取状态码,而非从其body流中获取。
该错误源于对Guzzle响应对象生命周期的误解:$response->getBody()返回的是一个Psr\Http\Message\StreamInterface实例(如GuzzleHttp\Psr7\Stream),它仅封装响应体内容,不包含HTTP状态码、头信息等元数据;而getStatusCode()是Psr\Http\Message\ResponseInterface的方法,必须作用于完整的响应对象本身。
在你的代码中,问题出现在两处:
-
成功分支:
$response = $response->getBody(); // ❌ 覆盖原Response对象为Stream $statusCode = $response->getStatusCode(); // ❌ Stream无此方法 → 报错
-
异常分支(虽未执行到,但逻辑同样错误):
$response = $e->getResponse(); $response = $response->getBody()->getContents(); // ❌ 先转为字符串,再试图调用getStatusCode() $statusCode = $response->getStatusCode(); // ❌ 字符串无此方法
✅ 正确写法:始终先提取状态码,再处理响应体内容。以下是修复后的完整方法:
public function send($user, $title, $body, $data = false, $type, $image = '')
{
$client = new \GuzzleHttp\Client();
$url = 'https://fcm.googleapis.com/fcm/send';
$serverKey = config('services.firebase.api_key');
$headers = [
'Content-Type' => 'application/json',
'Authorization' => 'key=' . $serverKey,
];
$fields = [
'registration_ids' => [$user['fcm_token']],
'to' => $user['fcm_token'],
'notification' => [
'title' => $title,
'body' => $body,
'sound' => 'default',
],
'priority' => 10,
'data' => $data,
'android' => ['priority' => 'high'],
];
$jsonPayload = json_encode($fields);
try {
$response = $client->request('POST', $url, [
'headers' => $headers,
'body' => $jsonPayload,
]);
// ✅ 正确:从Response对象获取状态码和body内容
$statusCode = $response->getStatusCode();
$responseBody = $response->getBody()->getContents(); // 或 ->toArray()(需启用json decoder)
} catch (\GuzzleHttp\Exception\ClientException $e) {
// ✅ 正确:先取状态码,再读取body
$response = $e->getResponse();
$statusCode = $response->getStatusCode(); // ← 关键:在getBody前调用!
$responseBody = $response->getBody()->getContents();
} catch (\GuzzleHttp\Exception\RequestException $e) {
// 可选:处理连接超时、DNS失败等网络层异常
$statusCode = $e->getCode() ?: 0;
$responseBody = $e->getMessage();
}
return [
'response' => $responseBody,
'statusCode' => $statusCode,
];
}
? 关键注意事项:
- Guzzle v7+ 基于 PSR-7 标准,严格分离 ResponseInterface(含状态码/头)与 StreamInterface(仅含正文),二者不可混用;
- getBody()->getContents() 返回 string,getBody()->__toString() 等效,均不可调用getStatusCode();
- 若需解析 JSON 响应,推荐使用 $response->getHeaderLine('Content-Type') 判断类型后,用 json_decode($response->getBody()->getContents(), true) 安全解析;
- Laravel 中建议使用 Http facade(底层已集成 Guzzle)替代手动实例化 Client,更简洁且自动处理异常分类。
遵循上述规范,即可彻底避免 Call to undefined method ... Stream::getStatusCode() 类错误,并构建健壮的 HTTP 集成逻辑。











