本地调试好好的 file_get_contents 抓接口,部署到服务器上返回 false,页面上什么都没有。打开报错才看到 failed to open stream: HTTP request failed。

它能干两件事

一是读本地文件,传路径进去返回整个文件内容。二是抓远程地址,只要 allow_url_fopen 打开,传 http 地址也能拿到响应体。区别在于后者走网络,超时、DNS、状态码都会影响结果,本地文件几乎不会失败,网络请求失败是常态。

读大文件别这么用

这个函数一次性把内容读进内存,抓一个 2G 的日志直接把内存撑爆。大文件要用 fopen 加 fgets 按行读,或者用 SplFileObject 迭代。只想数行数可以 count(file($path)),但 file 同样吃内存,超过 100M 还是老老实实走流式。

抓网页要配上下文

$ctx = stream_context_create(['http' =>
    ['timeout' => 5, 'method' => 'POST',
     'header' => 'Content-Type: application/json',
     'content' => $payload]]);
$r = file_get_contents($url, false, $ctx);

默认超时是 60 秒,生产代码一定要显式设小。抓 https 需要系统装了 CA 证书,否则报 certificate verify failed。返回 4xx 或 5xx 时函数返回 false 并抛 warning,用 @ 压制不是好习惯,应该配合 error_get_last 判断。

排查顺序

  • 看 php.ini:allow_url_fopen 是否 On,disable_functions 里有没有它。
  • 看响应头:打印 http_response_header 变量拿状态码。
  • 看权限:读本地文件时注意 open_basedir 限制和文件属主。
  • 换 curl:需要自定义头、超时、跟重定向时,curl 可控得多。