PHP用curl_setopt发POST请求需设CURLOPT_POST=>true和CURLOPT_POSTFIELDS;传数组自动urlencode并设application/x-www-form-urlencoded,传JSON需手动设Content-Type: application/json,且须检查json_encode结果及curl错误。

curl_setopt 设置 POST 方法和数据体
PHP 用 curl_setopt 发送 POST 请求,核心是两步:告诉 cURL 用 POST 方法,再把数据塞进请求体。不设 CURLOPT_POST 或漏掉 CURLOPT_POSTFIELDS,请求就还是 GET,或者发空体。
-
CURLOPT_POST => true是开关,必须显式设为true(不能只设1,某些旧版本会出问题) -
CURLOPT_POSTFIELDS接收数组或字符串:传数组会自动编码成application/x-www-form-urlencoded;传 JSON 字符串则需手动设Content-Type - 如果目标接口要
application/json,得额外加CURLOPT_HTTPHEADER,比如['Content-Type: application/json']
传数组 vs 传 JSON 字符串的区别
很多人卡在“为什么后端收不到数据”,其实是没分清两种常见场景的数据格式和 header 配合方式。
- 传关联数组:
curl_setopt($ch, CURLOPT_POSTFIELDS, ['name' => '张三', 'age' => 25])→ 自动 urlencode,body 是name=%E5%BC%A0%E4%B8%89&age=25,header 默认是application/x-www-form-urlencoded - 传 JSON:
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(['name' => '张三', 'age' => 25]))→ body 是原始 JSON 字符串,但必须手动加Content-Type: application/json,否则后端可能当普通表单解析失败 - 注意:
json_encode返回false时(比如含非法 UTF-8 字符),CURLOPT_POSTFIELDS会收到null,导致发空请求 —— 建议加if (false === $json = json_encode(...)) { die('JSON encode failed'); }
常见错误:POST 成功但后端 $_POST 为空
这通常不是 cURL 问题,而是服务端环境或 PHP 配置导致的解析失败。
- 检查目标服务器是否禁用了
php://input(影响 raw body 读取),或enable_post_data_reading = Off(极少见,但会导致$_POST始终为空) - 用
file_get_contents('php://input')在后端打印原始输入,确认数据确实到达 —— 如果有内容但$_POST空,说明是编码或 content-type 不匹配 - cURL 默认不发
Host头,某些 Nginx 配置下会 400;可加['Host: example.com']到CURLOPT_HTTPHEADER排查 - 别忽略 HTTPS 证书验证:开发时临时关掉
CURLOPT_SSL_VERIFYPEER => false和CURLOPT_SSL_VERIFYHOST => false,但上线前必须恢复
完整可运行示例(带错误处理)
以下是最小可靠模板,覆盖最常用表单提交场景:
立即学习“PHP免费学习笔记(深入)”;
$ch = curl_init('https://httpbin.org/post');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, ['user_id' => 123, 'token' => 'abc']);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
if ($error) {
die("cURL error: $error");
}
if ($httpCode !== 200) {
die("HTTP $httpCode");
}
echo $response;
真正容易被忽略的是:每次 curl_exec 后必须检查 curl_error 和 curl_getinfo(..., CURLINFO_HTTP_CODE) —— 很多“没反应”其实是 500 或超时,但代码没捕获就静默失败了。











