最简GET请求需new Client后调get(),但返回ResponseInterface,须显式getBody()->getContents()或json_decode()解析;Client应复用而非循环新建;非UTF-8响应需手动转码;form_params与json选项底层处理不同,不可混用;4xx/5xx默认不抛RequestException,需设http_errors=>true;超时分timeout和connect_timeout两级;Laravel的Http facade封装Guzzle但控制力弱,精细场景宜用原生Client。

怎么用 GuzzleHttp\Client 发起最简 GET 请求
直接 new 一个 Client,调 get() 就能发请求,但默认不自动解析响应体——你拿到的是 ResponseInterface 对象,不是 JSON 数组或字符串。
-
get()返回值必须显式调getBody()->getContents()或json_decode($res->getBody()->getContents(), true)才能拿到数据 - 别在循环里反复 new
Client,它自带连接池,复用实例更高效 - 如果目标接口返回非 UTF-8 编码(比如 GBK),
getContents()拿到的是原始字节,得自己用mb_convert_encoding()转
POST 提交表单或 JSON 数据的区别在哪
表单提交用 form_params,JSON 提交用 json,两者底层处理完全不同:前者自动设 Content-Type: application/x-www-form-urlencoded 并编码键值对;后者自动序列化数组、设 Content-Type: application/json。
- 误把
json当form_params用,服务端收不到字段,因为 body 是 raw JSON 字符串,不是标准表单格式 - 要传文件,必须用
multipart,不能塞在form_params里——后者会把CURLFile当字符串处理,导致上传失败 -
json选项不支持资源类型(如fopen()句柄),只接受数组或标量
为什么 RequestException 抓不到 404 或 500
Guzzle 默认把 4xx/5xx 当作“成功响应”处理,不会抛异常——只有网络层失败(如 DNS 错、连接超时)才触发 RequestException。
- 想让 404 也进
catch,得加配置:['http_errors' => true] - 但开了这个,正常业务错误(比如登录失败返回 401)也会中断流程,得在 catch 里用
$e->getResponse()->getStatusCode()判断具体状态码再决定是否重试或忽略 - 超时控制分两级:
timeout管整个请求耗时,connect_timeout只管建连阶段,后者默认 0(不限),容易卡死在 DNS 解析上
在 Laravel 里直接用 Http facade 还是原生 Guzzle
Laravel 的 Http facade 底层就是封装的 Guzzle,但砍掉了不少底层控制权——比如无法直接访问 StreamInterface、不支持自定义 handler stack、中间件机制也不一样。
立即学习“PHP免费学习笔记(深入)”;
- 需要流式读取大文件、或对接 S3 presigned URL 这种需精细控制 body 流的场景,绕过
Http直接用Client更稳 -
Http::withOptions(['verify' => false])看似和new Client(['verify' => false])一样,但前者在某些 Laravel 版本中会被 Guzzle 的默认 handler 忽略,仍校验证书 - 升级 Guzzle 版本(如从 6 升到 7)时,Laravel 自带的
Http可能不兼容新特性,比如Promise返回值变化,这时只能切回原生 client 控制依赖



















