Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/259.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用PHP和CURL发布多维数组_Php_Arrays_Post_Curl - Fatal编程技术网

使用PHP和CURL发布多维数组

使用PHP和CURL发布多维数组,php,arrays,post,curl,Php,Arrays,Post,Curl,我无法通过CURL将表单数据发布到位于不同主机上的接收PHP脚本 我得到一个数组到字符串的转换错误 这是我发布的数组的打印\r: Array ( [name] => Array ( [0] => Jason [1] => Mary [2] => Lucy ) [id] => 12 [status] => local [file] => @/test.txt )

我无法通过CURL将表单数据发布到位于不同主机上的接收PHP脚本

我得到一个
数组到字符串的转换
错误

这是我发布的数组的
打印\r

Array
(
    [name] => Array
    (
        [0] => Jason
        [1] => Mary
        [2] => Lucy
    )
    [id] => 12
    [status] => local
    [file] => @/test.txt
)
这是发生错误的行:

curl_setopt($this->ch, CURLOPT_POSTFIELDS, $post);
第三个参数必须是一个数组,因为我需要将
内容类型
标题设置为
多部分/表单数据
,因为我通过同一数组发送文件,因此我无法将数组转换为查询字符串或使用
http\u build\u query()

此外,我无法访问接收主机上的代码,因此无法序列化和取消序列化阵列

我假设name键作为数组的值是导致此错误的原因,我还假设
CURLOPT_POSTFIELDS
不支持多维数组。还有别的办法吗?还是我注定了


提前谢谢

涉及HTTP请求时,数组的概念实际上并不存在。PHP(可能还有其他服务器端语言)内置了逻辑,可以接收看起来像数组的请求数据,并在填充
$\u GET
$\u POST
等时将其作为数组放在一起

例如,从表单发布数组时,表单元素通常如下所示:

<form ...>
  <input name="my_array[0]">
  <input name="my_array[1]">
  <input name="my_array[2]">
</form>
curl_setopt($this->ch, CURLOPT_POSTFIELDS, curl_postfields_flatten($post));
array(
  'a' => 'a',
  'b' => array(
    'c' => array(
      'd' => 'd',
      'e' => array(
        'f' => 'f',
      ),
    ),
  ),
);
array(
 'b[c]' => '1',
 'b' => array(
   'c' => '2', 
  ),
);
这将导致您的
$post
数组如下所示:

Array
(
    [name[0]] => Jason
    [name[1]] => Mary
    [name[2]] => Lucy
    [id] => 12
    [status] => local
    [file] => @/test.txt
)

然后,您要发布的数组中的每个键都将是一个标量值,这是cURL所期望的,并且数组将按照您需要的方式表示为HTTP。

我认为您需要将选项作为字符串传递:

curl_setopt($this->ch, CURLOPT_POSTFIELDS, 'name[]=Jason&name[]=Mary&name[]=Lucy...');

然后,您应该能够通过CURLOPT_HTTPHEADER手动设置头。

您必须手动构建POST字符串,而不是将整个数组传入。然后,您可以使用以下内容覆盖curl的自动选择内容标题:

curl_setopt($c, CURLOPT_HTTPHEADER, array("Content-type: multipart/form-data"));

序列化/json序列化会更容易,但正如您所说,您无法控制接收端,因此需要做一些额外的工作。

最简单的解决方案是:

function http_build_query_for_curl( $arrays, &$new = array(), $prefix = null ) {

    if ( is_object( $arrays ) ) {
        $arrays = get_object_vars( $arrays );
    }

    foreach ( $arrays AS $key => $value ) {
        $k = isset( $prefix ) ? $prefix . '[' . $key . ']' : $key;
        if ( is_array( $value ) OR is_object( $value )  ) {
            http_build_query_for_curl( $value, $new, $k );
        } else {
            $new[$k] = $value;
        }
    }
}

$arrays = array(
    'name' => array(
        'first' => array(
            'Natali', 'Yura'
        )
    )
);


http_build_query_for_curl( $arrays, $post );

print_r($post);
$array = urldecode(http_build_query($array));
下面是在现实生活中使用的示例代码:


当您在上述要点中嵌套$params部分时,它将相应地对其进行分析,并准备通过curl进行发布。

curl选项
CURLOPT_POSTFIELDS
将接受字符串或简单数组,但不接受嵌套数组。尝试执行此操作将生成
数组到字符串转换
错误

但是
http\u build\u query()
可以处理嵌套数组,因此使用它将
$\u POST
数组转换为字符串,然后发送该字符串。那么你在哪里,

curl_setopt($ch, CURLOPT_POSTFIELDS, $_POST);
用这个代替

curl_setopt($ch, CURLOPT_POSTFIELDS, urldecode(http_build_query($_POST)));

首先,我要感谢丹尼尔·范德斯路易斯的贡献。根据他的意见,我从最初的问题中提出了这个问题:

<?php

function curl_postfields_flatten($data, $prefix = '') {
  if (!is_array($data)) {
    return $data; // in case someone sends an url-encoded string by mistake
  }

  $output = array();
  foreach($data as $key => $value) {
    $final_key = $prefix ? "{$prefix}[{$key}]" : $key;
    if (is_array($value)) {
      // @todo: handle name collision here if needed
      $output += curl_postfields_flatten($value, $final_key);
    }
    else {
      $output[$final_key] = $value;
    }
  }
  return $output;
}
此函数将按如下方式转换数组:

<form ...>
  <input name="my_array[0]">
  <input name="my_array[1]">
  <input name="my_array[2]">
</form>
curl_setopt($this->ch, CURLOPT_POSTFIELDS, curl_postfields_flatten($post));
array(
  'a' => 'a',
  'b' => array(
    'c' => array(
      'd' => 'd',
      'e' => array(
        'f' => 'f',
      ),
    ),
  ),
);
array(
 'b[c]' => '1',
 'b' => array(
   'c' => '2', 
  ),
);
为此:

array(
  'a' => 'a',
  'b[c][d]' => 'd',
  'b[c][e][f]' => 'f',
)
当出现如下键冲突时,它不会处理混合格式的情况:

<form ...>
  <input name="my_array[0]">
  <input name="my_array[1]">
  <input name="my_array[2]">
</form>
curl_setopt($this->ch, CURLOPT_POSTFIELDS, curl_postfields_flatten($post));
array(
  'a' => 'a',
  'b' => array(
    'c' => array(
      'd' => 'd',
      'e' => array(
        'f' => 'f',
      ),
    ),
  ),
);
array(
 'b[c]' => '1',
 'b' => array(
   'c' => '2', 
  ),
);
输出将仅包含该键的第一个值

array(
 'b[c]' => '1'
)

谢谢我不知道我能做到这一点。我添加了
CURLOPT\u HTTPHEADER
,并将数组传递到
http\u build\u query()
。工作完成了!感谢您提及http\u build\u query()。这对我来说就像一个符咒!在我的情况下,这不起作用。错误为警告:第0行的“未知”中的多部分/表单数据POST数据中缺少边界。对我有效的是Khristenko YuraThanks,因为你的回答,它没有完全回答这个问题,但它非常有洞察力!非常有帮助,谢谢!如果您有嵌套数组并且需要上载文件,那么您将需要它。我觉得这是更好的解决方案,因为它也可以轻松地处理文件上载。谢谢如果$post尚未定义,您只需添加
return$new
在函数的末尾,我(在我的代码中)将其更改为返回
$new
数组。您是否有任何理由使用
和$new
(通过引用)并返回
void
,而不只是返回
$new