使用PHP和CURL发布多维数组
我无法通过CURL将表单数据发布到位于不同主机上的接收PHP脚本 我得到一个使用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 )
数组到字符串的转换
错误
这是我发布的数组的打印\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
?