You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP Curl请求在Postman外失效:含数组的formdata问题排查

问题:PHP cURL POST请求中registration_attributes数组构建导致"Missing"错误

背景

我用以下PHP cURL代码发起POST请求,该请求在Postman中可正常运行,但在生产服务器上返回响应{"registration_attributes":["Missing"]}。请问我构建registration_attributes数组的方式是否存在错误?

原代码:

$curl = curl_init();
curl_setopt_array($curl, array( CURLOPT_URL => "https://www.sample.com/v2/clients?token=DMfJjzWLngIn0JBHA0gWcg", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => "", CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 30, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => "------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name=\"active_registration_id\"

123
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name=\"language_id\"

79
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name=\"archived\"

{{archived}}
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name=\"enabled\"

{{enabled}}
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name=\"password\"

SamplePassword
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name=\"password_confirmation\"

SamplePassword
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name=\"registration_attributes[first_name]\"

Justin
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name=\"registration_attributes[last_name]\"

Trudeau
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name=\"registration_attributes[email]\"

email@sample.com
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name=\"registration_attributes[telephone_1]\"

555-555-5555
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name=\"registration_attributes[date_of_birth]\"

1943-10-10
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name=\"registration_attributes[gender]\"

Male
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name=\"registration_attributes[referral_code]\"

Ample Clinic 123
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name=\"registration_attributes[status]\"

Registration Pending
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name=\"For Additional Permitted Parameters:\"

See Registration Parameters
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name=\"registration_attributes[date_of_birth]\"

1943-10-10
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name=\"registration_attributes[gender]\"

Male
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name=\"registration_attributes[referral_code]\"

Ample Clinic 123
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name=\"registration_attributes[status]\"

Registration Pending
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; ", CURLOPT_HTTPHEADER => array( "Content-Type: application/x-www-form-urlencoded", "content-type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW" ), )); $response = curl_exec($curl); $err = curl_error($curl); curl_close($curl); if ($err) { echo "cURL Error #:" . $err; } else { echo $response; }

问题分析与解决方案

你的代码里有几个关键问题导致服务器无法正确解析registration_attributes字段:

  1. 冲突的Content-Type头
    你同时设置了application/x-www-form-urlencoded和multipart/form-data两种Content-Type,这会让服务器搞不清该用哪种格式解析请求体,直接导致表单数据解析失败。

  2. 手动拼接multipart内容的错误

    • 你手动构建的POST数据末尾有一段不完整的字段:------WebKitFormBoundary7MA4YWxkTrZu0gW Content-Disposition: form-data; ,没有完成字段定义,也没有正确的结束边界标记(正确的结束边界应该是------WebKitFormBoundary7MA4YWxkTrZu0gW--,末尾带两个减号)。
    • 重复提交了registration_attributes下的多个字段(比如date_of_birth、gender等),这也可能干扰服务器的解析逻辑。
  3. 手动构建multipart的不可靠性
    手动拼接multipart/form-data格式很容易出错,比如换行符、边界字符串不一致、字段格式错误等,Postman会自动处理这些细节,所以能正常运行,但你的手动拼接版本有漏洞。

修正后的代码(推荐方案)

直接用PHP数组组织POST数据,让cURL自动处理multipart/form-data的格式和边界,这是最可靠的方式:

$curl = curl_init();

// 用数组整理所有POST参数,自动支持嵌套数组格式
$postData = [
    'active_registration_id' => 123,
    'language_id' => 79,
    'archived' => '{{archived}}',
    'enabled' => '{{enabled}}',
    'password' => 'SamplePassword',
    'password_confirmation' => 'SamplePassword',
    'registration_attributes' => [
        'first_name' => 'Justin',
        'last_name' => 'Trudeau',
        'email' => 'email@sample.com',
        'telephone_1' => '555-555-5555',
        'date_of_birth' => '1943-10-10',
        'gender' => 'Male',
        'referral_code' => 'Ample Clinic 123',
        'status' => 'Registration Pending'
    ],
    'For Additional Permitted Parameters:' => 'See Registration Parameters'
];

curl_setopt_array($curl, [
    CURLOPT_URL => "https://www.sample.com/v2/clients?token=DMfJjzWLngIn0JBHA0gWcg",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_ENCODING => "",
    CURLOPT_MAXREDIRS => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    CURLOPT_CUSTOMREQUEST => "POST",
    // 直接传入数组,cURL会自动生成正确的multipart/form-data格式
    CURLOPT_POSTFIELDS => $postData,
    // 不需要手动设置Content-Type,cURL会自动添加正确的头信息
    CURLOPT_HTTPHEADER => []
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
    echo "cURL Error #:" . $err;
} else {
    echo $response;
}

关键修正点说明

  • 用数组组织参数,嵌套的registration_attributes数组会被cURL自动转换成正确的表单字段格式(比如registration_attributes[first_name])。
  • 移除了冲突的Content-Type头,让cURL自动处理,避免格式混淆。
  • 删除了重复的字段,确保请求体干净无歧义。

如果一定要手动构建multipart内容,务必确保:

  • 所有边界字符串完全一致,结束边界必须带两个减号。
  • 每个字段的格式正确,字段名和值之间有正确的换行。
  • 只设置一个正确的Content-Type头。

内容的提问来源于stack exchange,提问作者Jeremy Giles

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:00:14