Guzzle调用时报错Header value must be scalar问题排查
Guzzle 触发
Header value must be scalar or null but array provided 报错的原因与修复 核心根因
你对 GuzzleHttp\Psr7\Request 构造函数的参数格式理解错误,传参结构不符合预期。
Request构造函数的参数顺序固定为:(string $method, $uri, array $headers = [], $body = null, string $version = '1.1'),第三个参数要求直接传入请求头关联数组本身,而非包含headers、body等键的配置数组。- 从报错堆栈第5行可以看到,
Request构造函数收到的第三个参数是你传入的整个$options数组,而非预期的请求头数组:此时setHeaders方法会把$options的每个键值对当成请求头的键和值,当处理对应值为数组的场景时,直接触发「请求头值不能为数组」的校验逻辑。
对组件设计的澄清
Guzzle 的 Psr7 组件确实支持数组格式的请求头值,但指的是单个请求头允许多个值的一维数组场景,例如:
// 正确的数组格式请求头值:单个Accept头对应多个MIME类型 $headers = [ 'Accept' => ['text/html', 'application/json'] ];
这种格式会被组件自动处理为多个同名称的请求头,和你当前误传的二维配置数组完全不是一回事。
修复方案
方案1:调整 Request 构造函数的传参(适配现有写法)
直接把配置数组拆分为对应参数传入:
private function send(string $uri, string $method, $body): bool { if ($this->getTokenValid()) { $headers = [ 'Authorization' => sprintf("Bearer %s", $this->token), 'Ocp-Apim-Subscription-Key' => SUBSCRIPTION_ID, 'Content-Type' => 'application/json' ]; // 按参数顺序传:方法、URI、请求头数组、请求体 $request = new Request($method, $uri, $headers, $body); try { $resp = $this->client->send($request); return $resp->getReasonPhrase(); } catch (ClientErrorResponseException $e) { error_log($e->getMessage()); return false; } } else { error_log('Not authenticated'); return false; } }
方案2:使用 Guzzle Client 原生的 request 方法(更推荐)
Guzzle Client 的 request 方法第三个参数本身就是包含 headers、body 等配置项的选项数组,更符合你原本的写法逻辑,无需手动实例化 Request:
private function send(string $uri, string $method, $body): bool { if ($this->getTokenValid()) { $options = [ 'headers' => [ 'Authorization' => sprintf("Bearer %s", $this->token), 'Ocp-Apim-Subscription-Key' => SUBSCRIPTION_ID, 'Content-Type' => 'application/json' ], 'body' => $body ]; try { // Client->request(方法, URI, 配置选项数组) $resp = $this->client->request($method, $uri, $options); return $resp->getReasonPhrase(); } catch (ClientErrorResponseException $e) { error_log($e->getMessage()); return false; } } else { error_log('Not authenticated'); return false; } }
内容的提问来源于stack exchange,提问作者tjb74
相关产品推荐
相关产品推荐

