symfony 2 不支持 httpclient 组件,因其始于 symfony 4.3;应改用 guzzlehttp v3 并作为 service 注册,配合 batch 控并发,手动处理百度 api 的 json 解析、bom 清理、缓存、重试及 token 刷新。

Symfony 2 不支持原生 HttpClient,强行用会报 Class 'Symfony\Component\HttpClient\HttpClient' not found 错误。别硬套新版本写法,得换路子。
为什么不能直接用 Symfony\Component\HttpClient\HttpClient
Symfony 2.8 是最后一个 LTS 版本,而 HttpClient 组件是 Symfony 4.3 才引入的。你看到的所有 HttpClient::create()、$response->toArray() 文档,对 Symfony 2 来说根本不存在。
- 试图
composer require symfony/http-client会失败:该组件最低要求 Symfony 4.3+ - 手动复制类或降级安装高版本组件,会导致依赖冲突、事件监听器失效、Kernel 初始化崩溃
- 已有项目若升级到 Symfony 4+,必须重写路由、服务容器、Bundle 加载逻辑——这不是“调用 API”的问题,是框架迁移问题
Symfony 2 实际可用的并发方案
只能靠外部 HTTP 客户端 + 手动并发控制。推荐用 GuzzleHttp\Client(v3.x 或 v6.x,注意兼容 PHP 版本),配合 Promise 实现并发请求。
- 装 Guzzle v3(适配 PHP 5.3+,兼容 Symfony 2.8):
composer require guzzlehttp/guzzle:~3.9 - 避免用 v6+ 的
AsyncClient—— Symfony 2 的 autoloader 和事件循环不兼容 PSR-18/PSR-7 - 不要在 Controller 里 new Client();应定义为 service,绑定到 container,方便复用和 mock
- 批量请求时,用
GuzzleHttp\Batch(v3)或each_limit(v6)控并发数,防止百度 API 触发限流(默认 QPS ≤ 5)
示例(Guzzle v3):
use GuzzleHttp\Batch;
$batch = new Batch($client, 3); // 最大并发 3
foreach ($keywords as $kw) {
$batch->add($client->getAsync("https://aip.baidubce.com/rpc/2.0/xxx?kw={$kw}&access_token={$token}"));
}
$responses = $batch->send(); // 返回 Guzzle\Http\Message\Response[]
百度 API 响应解析的坑
百度多数接口返回 JSON,但错误时不返回标准 HTTP 状态码(比如鉴权失败仍返回 200 + HTML 错误页),json_decode($response->getBody(), true) 容易 silent fail 或抛 JSON_ERROR_SYNTAX。
- 务必先检查
$response->getHeader('Content-Type')是否含application/json - 再用
json_last_error()校验解码结果,别直接假设isset($data['error_code']) - 百度翻译、文心一言等接口在 token 过期时返回
200 OK+ JSON{"error_code":110,"error_msg":"Access token invalid"},需业务层识别,不能只看状态码 - 响应体可能带 BOM 头(尤其 Windows 环境生成的 token),
trim($response->getBody(), "\xEF\xBB\xBF")再 decode
缓存与重试必须自己补全
Symfony 2 没有内置 retry middleware、no-op cache pool,这些得手写。
- 用
Doctrine\Common\Cache\ApcCache或FileCache缓存百度响应(key 建议含access_token+query+timestamp) - 重试逻辑要包裹在 service 层:捕获
GuzzleHttp\Exception\RequestException,判断$e->getResponse()->getStatusCode()是否为 502/503/429,再 sleep(1) 后重试(最多 2 次) - 百度 API 的
access_token有效期 30 天,但实际常因密钥变更提前失效,需监听error_code === 110并触发 token 刷新流程
真正的难点不在并发本身,而在错误响应的语义归一化——百度返回的“成功”和“失败”混在同一 HTTP 状态下,得靠字段判断,这个逻辑一旦漏掉,批量请求就会静默丢数据。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











