php模拟post请求传数组参数_php数组post发送教程【步骤】

cURL传数组时自动urlencode为x-www-form-urlencoded格式,后端可直接解析为$_POST;传JSON需手动json_encode并设Content-Type: application/json。

php模拟post请求传数组参数_php数组post发送教程【步骤】

PHP cURL 发送 POST 数组参数时,curl_setopt($ch, CURLOPT_POSTFIELDS, $arr) 会自动转成 application/x-www-form-urlencoded

这是最常用也最容易出错的方式:直接传 PHP 关联数组给 CURLOPT_POSTFIELDS。cURL 会帮你 urlencode 并拼接成 a=1&b[0]=x&b[1]=y 这种格式——后端(尤其是 PHP)能原样解析成 $_POST 数组。

但注意:这种行为仅在 $arr 是数组且未被 json_encode 时生效;如果传的是 JSON 字符串或对象,cURL 就不会自动处理键名嵌套规则。

  • ✅ 正确:传递 ['name' => 'foo', 'tags' => ['php', 'curl']] → 后端 $_POST['tags'][0] 可取到 'php'
  • ❌ 错误:先 json_encode($arr) 再传入 → cURL 当作纯文本发,Content-Type 默认仍是 application/x-www-form-urlencoded,后端收不到 $_POST
  • ⚠️ 注意:curl_setopt($ch, CURLOPT_POSTFIELDS, $arr) 会忽略你手动设置的 Content-Type 头,除非你显式调用 curl_setopt($ch, CURLOPT_HTTPHEADER, [...])

要发 JSON 数组,必须手动设 Content-Type: application/json 并传字符串

当目标接口明确要求 JSON(比如 Laravel 的 Request::isJson() 或 Node.js 接口),就不能依赖 cURL 自动编码。必须自己 json_encode,并覆盖请求头。

$data = ['items' => [1, 2, 3], 'meta' => ['source' => 'php-curl']];
$ch = curl_init('https://api.example.com/submit');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
    'Accept: application/json'
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($ch);
  • 不设 Content-Type → 大部分服务端会当成普通表单解析,json_encode 后的字符串进不了 $_POST,可能进 php://input
  • PHP 后端若想读 JSON,得用 json_decode(file_get_contents('php://input'), true),不是 $_POST
  • 某些框架(如 ThinkPHP)对 php://input 有读取限制,需确认是否开启 always_populate_raw_post_data(PHP 5.6+ 已废弃)

嵌套数组深层键名失效?检查是否用了数字索引导致 key 被丢弃

cURL 对数组的 urlencode 行为遵循 PHP 的 http_build_query 规则。如果你传的是 [0 => 'a', 1 => 'b'],它会变成 0=a&1=b,而非 arr[]=a&arr[]=b —— 后端 PHP 收到的是两个独立变量,不是数组。

立即学习PHP免费学习笔记(深入)”;

  • ✅ 想让后端得到 $_POST['arr'] = ['a','b'],应传:['arr' => ['a', 'b']]['arr[]' => ['a','b']]
  • ✅ 更稳妥:用 http_build_query(['arr' => ['a','b']], '', '&', PHP_QUERY_RFC3986) 显式构造字符串再传给 CURLOPT_POSTFIELDS
  • ⚠️ 特别注意:如果数组键含点号(.)或空格,http_build_query 会转义,但某些老版本 Nginx + PHP-FPM 会截断或忽略这类 key

调试时看不到真实发送内容?用 curl_setopt($ch, CURLOPT_VERBOSE, 1) 或抓包

光看代码很难判断最终发出的 body 和 header 是什么。尤其当数组结构复杂、header 覆盖失败、或服务端返回 400 却没提示具体哪错了。

  • 临时加 curl_setopt($ch, CURLOPT_VERBOSE, 1),输出会包含完整请求头和 body(注意重定向可能干扰)
  • 更可靠:用 tcpdumpWireshark 抓本地回环(lo),过滤 port 80 or port 443,确认实际发出的 Content-Type 和原始 payload
  • 快速验证:把 cURL 请求复制到 Postman,改用 form-data / x-www-form-urlencoded / raw JSON 三种模式分别试,比对响应差异

数组 POST 看似简单,但键名编码规则、Content-Type 匹配、服务端解析逻辑三者稍有错位,就收不到预期数据。重点盯住「发出去的是什么」和「对方按什么规则解」这两头,而不是只看 PHP 侧怎么构造数组。

https://www.php.cn/faq/2035004.html

发表回复

Your email address will not be published. Required fields are marked *