
curl_exec() 返回 false 怎么判断真实错误原因
直接用 curl_exec() 的返回值做真假判断会漏掉很多关键信息——比如 HTTP 状态码 404、500,它照样返回字符串(非 false),而真正失败时(如 DNS 解析失败、连接超时)才返回 false。但 false 本身不告诉你错在哪。
必须配合 curl_errno() 和 curl_error() 才能定位问题类型:
-
curl_errno($ch)返回整数错误码,比如CURLE_COULDNT_RESOLVE_HOST(6)、CURLE_OPERATION_TIMEDOUT(28) -
curl_error($ch)返回可读字符串,如"Could not resolve host: api.example.com" - 注意:必须在
curl_exec()之后、curl_close()之前调用,否则清空了错误状态
file_get_contents() 报 Warning: failed to open stream 怎么捕获
PHP 默认把 HTTP 请求失败当 warning 抛出,不进异常,try/catch 拦不住。想统一处理,得关掉 allow_url_fopen 的警告行为,改用上下文选项控制错误流。
正确做法是用 stream_context_create() 配置 http 选项,并设 ignore_errors => true:
立即学习“PHP免费学习笔记(深入)”;
$opts = [
'http' => [
'method' => 'GET',
'timeout' => 5,
'ignore_errors' => true, // 关键:让 4xx/5xx 响应也返回 body
]
];
$ctx = stream_context_create($opts);
$result = file_get_contents('https://api.example.com/data', false, $ctx);
// 然后检查 $http_response_header 或用 get_headers() 判断状态码
不设 ignore_errors,遇到 404 就直接 warning + 返回 false,根本拿不到响应头或 body。
超时设置不生效?重点看 connect_timeout 和 timeout 区别
很多人只设 CURLOPT_TIMEOUT,结果 DNS 卡住十几秒也不触发超时——因为这个参数管的是「整个请求过程」,不包括 DNS 解析和 TCP 连接建立阶段。
真正要防卡死,得分开控制:
-
CURLOPT_CONNECTTIMEOUT_MS:限制 DNS + TCP 连接耗时(毫秒级,推荐设 3000) -
CURLOPT_TIMEOUT_MS:限制从连接成功到响应结束的总耗时(毫秒级,推荐设 8000) - 如果只用秒级选项(如
CURLOPT_CONNECTTIMEOUT),在高延迟网络下可能不够精确 - 注意:cURL 7.16.2+ 才支持
_MS后缀;旧版本只能用秒,且最小为 1 秒
HTTPS 请求失败常见于证书验证,但别急着关 CURLOPT_SSL_VERIFYPEER
报错 "SSL certificate problem: unable to get local issuer certificate",说明本地没装 CA 根证书包,不是服务端问题。
安全做法是补全证书路径,而不是关验证:
- 下载最新 CA 包(如 cacert.pem),存到项目目录
- 用
CURLOPT_CAINFO指向它:curl_setopt($ch, CURLOPT_CAINFO, '/path/to/cacert.pem') - 关掉
CURLOPT_SSL_VERIFYPEER是临时绕过,生产环境等于裸奔 - Windows 下 PHP 自带的 OpenSSL 可能找不到系统证书,必须显式指定
证书路径写错、文件没读取权限、或用了相对路径却在 CLI 下执行——这些都比关验证更容易被忽略。











