GuzzleHttp\Client 最简用法是直接 new 实例发起 GET/POST,支持 JSON 自动解析、重定向、超时控制;注意 URL 前缀、base_uri 与路径拼接、query/json 选项正确使用,需检查状态码并安全处理 JSON 响应。

用 GuzzleHttp\Client 发起 GET/POST 请求最简写法
直接 new 一个 Client 实例就能发请求,不用配一堆东西。默认支持 JSON 自动解析、重定向跟随、连接超时控制。
常见错误是漏掉 http:// 或 https:// 前缀,导致抛出 Invalid URL 错误;还有人把完整 URL 写进 base_uri,结果拼接后路径重复。
-
base_uri只填根地址,比如'https://api.example.com/v1/',后面request()的 path 不要带斜杠开头 - GET 参数用
query数组传,Guzzle 自动编码,别手动拼在 URL 里 - POST 提交 JSON 数据,设
json选项(自动设 header + 序列化),别用body+json_encode()再自己设 header
$client = new \GuzzleHttp\Client(['base_uri' => 'https://httpbin.org/']);
$response = $client->get('get', ['query' => ['key' => 'value']]);
$data = $response->getBody()->getContents(); // 或 ->toArray() 如果是 JSON
处理 REST 返回的 JSON 数据和状态码
response->getStatusCode() 必须检查,Guzzle 不会自动 throw 异常(除非你开 http_errors => true)。4xx/5xx 响应体里往往有错误详情,直接丢掉就很难定位问题。
- 用
$response->getHeaderLine('Content-Type')确认是不是application/json,再决定是否调->toArray() -
->toArray()在非 JSON 响应下会抛RuntimeException,建议包 try/catch - 需要统一错误处理?在 Client 构造时加
'http_errors' => false,自己判断状态码分支
try {
$res = $client->post('login', ['json' => ['user' => 'a', 'pass' => 'b']]);
if ($res->getStatusCode() >= 400) {
$err = $res->toArray();
throw new Exception($err['message'] ?? 'API error');
}
return $res->toArray();
} catch (GuzzleHttp\Exception\RequestException $e) {
// 网络失败、DNS 错、连接超时等
}
设置超时、重试和基础认证(Basic Auth)
不设超时,线上服务可能卡住整个 PHP 进程;不设重试,临时网络抖动就失败;Basic Auth 写错格式会导致 401 且服务端日志看不出是凭据问题。
立即学习“PHP免费学习笔记(深入)”;
-
timeout控制整个请求耗时上限(含 DNS、连接、发送、接收),单位秒,建议设 5~10 -
connect_timeout单独控连接阶段,设 2~3 秒更稳妥 - 重试要用
GuzzleHttp\Middleware::retry()+HandlerStack,不能只靠retries配置项(它已废弃) - Basic Auth 直接传
auth数组:['username', 'password', 'basic'],别手动生成 Authorization header
$stack = \GuzzleHttp\HandlerStack::create();
$stack->push(\GuzzleHttp\Middleware::retry(
function ($retries, $request, $response, $exception) {
return $retries < 3 && ($exception || ($response && $response->getStatusCode() >= 500));
}
));
$client = new \GuzzleHttp\Client([
'handler' => $stack,
'timeout' => 8,
'auth' => ['myuser', 'mypass']
]);
上传文件和处理大响应体的内存安全做法
用 multipart 上传文件时,contents 值如果是字符串,Guzzle 会全读进内存;大文件或高并发下容易 OOM。流式处理响应体也一样,getContents() 会加载全部内容到内存。
- 上传文件优先用
'contents' => fopen('/path/to/file', 'r'),让 Guzzle 流式读取 - 响应体很大?用
$response->getBody()->read(8192)分块读,或直接fopen('php://temp', 'w+')中转 - 别在循环里反复 new Client,复用实例;它本身是线程安全的,且内部管理连接池
复杂点在于 multipart 字段混合(文本+文件)、自定义 boundary、或者需要监听上传进度——这些得用 Stream + MultipartStream 手动构造,不是开箱即用的场景。











