file_get_contents() 最快但仅支持 GET 且无法设 header 或 POST 数据,适合公开只读接口;调 RESTful API 必须用 curl_init(),因其可精确控制方法、header、SSL、超时及错误捕获。

用 file_get_contents() 调 API 最快,但不支持 POST 或带 header
多数人一上来就试 file_get_contents(),确实简单:直接传个 URL 就能拿到响应。但它本质是 GET 请求,没法发 JSON 数据、加 Authorization 头,甚至 404 或 500 错误时也只返回空或 false,没法定位问题。
- 适合场景:调公开的只读接口,比如天气、汇率等无需鉴权的 GET 接口
- 常见错误现象:
file_get_contents(): failed to open stream: HTTP request failed!—— 这说明服务器返回了非 2xx 状态码,但你完全看不到 body 和具体 status - 要让它带 header?不行。想传 JSON?得手动拼 query string,不能走 request body
- PHP 默认可能禁用该函数(
allow_url_fopen=Off),线上环境常被关掉,一上线就报错
必须用 curl_init() 的三个刚性理由
真正调 RESTful API,绕不开 curl_init()。它不是“更高级”,而是唯一能精确控制请求方法、header、超时、SSL 验证和错误捕获的方式。
- POST 发 JSON 必须设:
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data))+curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']) - 鉴权失败?检查
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer xxx'])是否漏了空格或大小写(比如Bearer写成bearer) - 本地调试通、线上 500?大概率是 SSL 验证问题 —— 别加
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false),应配好 CA 包路径:curl_setopt($ch, CURLOPT_CAINFO, '/path/to/cacert.pem') - 忘记
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true)?结果会直接 echo 出来,而不是返回字符串,后续json_decode()就崩了
json_decode() 返回 null?先查 json_last_error_msg()
API 返回看起来像 JSON,但 json_decode() 却返回 null,90% 是因为响应里混了不可见字符(BOM、换行、空格)或编码不对。别急着改代码逻辑,先看原始响应。
- 调试时加一句:
var_dump($response); echo 'JSON error: ' . json_last_error_msg(); - 常见原因:API 返回的是 UTF-8+BOM,而 PHP
json_decode()不认;用trim($response, "\xEF\xBB\xBF")去 BOM - 响应是 gzip 压缩的?cURL 默认不自动解压,得加:
curl_setopt($ch, CURLOPT_ENCODING, '') - 返回 HTML 错误页(比如 Nginx 502)却被当 JSON 解析?先用
strpos($response, '{') === 0或mb_detect_encoding()粗筛内容类型
别在循环里反复 curl_init(),复用句柄更稳
批量调同一个 API(比如查 100 个用户信息),每次新建 cURL 句柄不仅慢,还容易触发连接池耗尽或 TIME_WAIT 暴增。cURL 支持复用句柄,改几行就能省下一半时间。
立即学习“PHP免费学习笔记(深入)”;
- 初始化一次:
$ch = curl_init(); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - 循环内只改 URL 和参数:
curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); - 记得每次调用后
curl_exec($ch),不要curl_close($ch)—— 留到循环结束再关 - 注意:复用时 header 不会自动清空,如果某次需要不同 header,得用
curl_setopt($ch, CURLOPT_HTTPHEADER, [...])显式重设
curl_exec() 返回 false 时,必须立刻接 curl_error($ch) 和 curl_getinfo($ch, CURLINFO_HTTP_CODE),不然永远在猜。



















