curl_init() 是PHP原生发送POST请求最稳妥方式,需设CURLOPT_POST、CURLOPT_POSTFIELDS、CURLOPT_RETURNTRANSFER和CURLOPT_TIMEOUT;发JSON须json_encode()并设Content-Type头;禁用SSL验证仅限调试,务必检查curl_exec返回值及curl_error。

用 curl_init() 发送 POST 请求最稳妥
PHP 原生发 POST,curl_init() 是目前兼容性最好、控制力最强的方式,比 file_get_contents() 配 stream_context_create() 更直观,也比废弃的 http_post_data() 可靠得多。
常见错误是没设 CURLOPT_RETURNTRANSFER,导致返回 bool(true) 而不是响应体;或者漏掉 CURLOPT_POST 或 CURLOPT_POSTFIELDS,请求变成 GET 或直接空发。
- 必须显式设置
CURLOPT_POST => true -
CURLOPT_POSTFIELDS接收数组(自动编码为application/x-www-form-urlencoded)或字符串(需手动设Content-Type) - 建议始终开启
CURLOPT_RETURNTRANSFER和CURLOPT_HEADER(调试时设为true,上线前关掉) - 超时务必设,比如
CURLOPT_TIMEOUT => 10,避免阻塞
$ch = curl_init('https://api.example.com/login');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, ['username' => 'admin', 'password' => '123']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
发送 JSON 数据要手动处理 Content-Type
如果目标接口要求 Content-Type: application/json(比如多数 REST API),不能直接传数组给 CURLOPT_POSTFIELDS,否则会发成表单格式,后端收不到 json_decode(file_get_contents('php://input')) 的数据。
必须把数组 json_encode() 成字符串,并显式设置请求头。
立即学习“PHP免费学习笔记(深入)”;
- 用
json_encode(['key' => 'val'])构造请求体 - 通过
CURLOPT_HTTPHEADER加入Content-Type: application/json - 注意检查
json_last_error(),避免空数组或非法字符导致编码失败
$data = json_encode(['email' => 'user@example.com', 'token' => 'abc123']);
$ch = curl_init('https://api.example.com/webhook');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
用 file_get_contents() 发 POST 很容易出错
虽然语法更短,但 stream_context_create() 对参数名和嵌套层级敏感,稍不注意就发不出数据,而且错误提示极不友好(常返回 false 且无日志)。
典型问题包括:http 数组写成顶层键而非子数组、content 没做 http_build_query() 或 json_encode()、漏掉 method 设置。
-
method必须大写,如'POST' -
content必须是字符串,不能是数组 - 若发 JSON,记得加
header项并包含Content-Type - 不推荐在生产环境用这种方式,调试困难,异常难捕获
$opts = [
'http' => [
'method' => 'POST',
'header' => "Content-Type: application/json\r\n",
'content' => json_encode(['id' => 123])
]
];
$result = file_get_contents('https://api.example.com/item', false, stream_context_create($opts));
别忽略 HTTPS 证书验证和重定向
本地开发时用 CURLOPT_SSL_VERIFYPEER => false 看似省事,但上线后会因证书校验失败而静默失败;同样,不处理重定向(CURLOPT_FOLLOWLOCATION)可能导致 302 后拿不到真实响应。
- 线上环境必须保留
CURLOPT_SSL_VERIFYPEER => true(PHP 5.6+ 默认开启) - 如需跟随跳转,加上
CURLOPT_FOLLOWLOCATION => true,但注意某些 API 明确禁止重定向 - 用
curl_error($ch)和curl_errno($ch)检查底层错误,比如CURLE_SSL_CACERT表示证书路径不对 - 自建 CA 或内网环境,可通过
CURLOPT_CAINFO指定证书路径
curl_init() 的容错和可观测性远高于其他方式。最容易被忽略的是:没检查 curl_exec() 返回值是否为 false,以及没用 curl_error() 捕获连接层失败——这些不会抛异常,但会导致逻辑误判。











