
本文介绍使用 Guzzle HTTP 客户端时,如何通过 GuzzleHttp\Psr7\Query::build() 手动构建包含多个同名键(如 item_id=123&item_id=456)的查询字符串,避免自动编码异常和 400 错误。
本文介绍使用 guzzle http 客户端时,如何通过 `guzzlehttp\psr7\query::build()` 手动构建包含多个同名键(如 `item_id=123&item_id=456`)的查询字符串,避免自动编码异常和 400 错误。
在 Guzzle 中,默认的 'query' 选项会将关联数组直接转换为 URL 查询字符串。但当需要传递多个同名参数(例如 item_id=8159&item_id=123&item_id=456)时,若简单地将 'item_id' => ['8159', '123', '456'] 传入 'query',Guzzle 默认行为可能将其序列化为 item_id[0]=8159&item_id[1]=123(即带数组下标的形式),导致服务端无法识别,甚至返回 400 Bad Request —— 这正是你遇到 = 被编码为 [、] 等乱码的原因。
✅ 正确做法是:不依赖 Guzzle 自动序列化数组,而是手动构建符合 RFC 3986 标准的重复参数查询字符串。Guzzle 提供了底层工具 GuzzleHttp\Psr7\Query::build(),它支持将含重复键的数组(如 'item_id' => ['8159', '123', '456'])生成标准的 item_id=8159&item_id=123&item_id=456 格式。
✅ 正确实现步骤
-
引入 Query 构建器(需确保已安装 guzzlehttp/psr7):
use GuzzleHttp\Psr7\Query;
-
构造含重复键的参数数组:
$query_params = [ 'test' => 'abc', 'test2' => true, 'limit' => 10, 'item_id' => ['8159', '123', '435', '333'], // 多个值 → 多个同名参数 ]; -
手动构建查询字符串并传入 query 选项:
$response = $this->client->request('GET', $endpoint, [ 'headers' => [ 'X-API-KEY' => KEY, ], 'query' => Query::build($query_params), // ← 关键:显式构建 ]);
⚠️ 注意事项:
- 不要将 'query' => $query_params 直接传入(Guzzle 会按 PHP 数组规则序列化,产生 item_id[0]=...);
- Query::build() 会自动进行 URL 编码(如空格→%20,中文→UTF-8百分号编码),无需额外处理;
- 若使用旧版 Guzzle(
- 服务端必须支持重复参数解析(绝大多数 REST API 均支持,如 Laravel、Express、Spring Boot 默认可接收 item_id[] 或直接多值)。
? 小技巧:如需调试生成的 URL,可打印 Query::build($query_params) 查看结果:
echo Query::build($query_params); // 输出:test=abc&test2=1&limit=10&item_id=8159&item_id=123&item_id=435&item_id=333
通过此方式,你既能保持代码清晰性,又能精准控制查询字符串格式,彻底规避因重复参数引发的编码错误与服务端解析失败问题。











