2010-09-22 53 views
41

我无法通过CURL将表单数据发布到位于不同主机上的接收PHP脚本。使用PHP和CURL发布多维数组

我得到一个错误Array to string conversion

这是数组我张贴的print_r

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

这是发生错误的行:

curl_setopt($this->ch, CURLOPT_POSTFIELDS, $post); 

第三个参数必须是一个数组,因为我需要将Content-Type标头设置为multipart/form-data,因为我通过这个相同的数组发送文件,因此我无法将数组转换为查询字符串或使用http_build_query()

此外,我没有访问接收主机上的代码,所以我不能序列化和反序列化数组。

我假设名称键值为数组是导致此错误的原因,我还假设CURLOPT_POSTFIELDS不支持多维数组。有没有其他解决方法或注定?

在此先感谢!

回答

23

你不得不手动构建POST字符串,而不是将整个阵列,然后你可以重写卷曲的自动选择的内容标头:

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

串行化/ JSON-ifying会更容易,但正如你所说,你无法控制接收端,所以你有一些额外的工作要做。

+4

谢谢!我其实并不知道我可以这样做。我添加了'CURLOPT_HTTPHEADER'并将我的数组传递给'http_build_query()'。任务完成! – 2010-09-23 09:38:46

+0

感谢您提及'http_build_query()'。它对我来说就像一个魅力! – mccbala 2013-09-16 08:10:58

+1

在我的情况下,这是行不通的。错误是**警告:第0行**中未知的multipart/form-data POST数据中缺少边界。什么对我来说是[这篇文章](http://stackoverflow.com/a/8224117/1057527)Khristenko Yura – machineaddict 2014-04-11 09:43:01

27

当涉及到HTTP请求时,数组的概念并不存在。 PHP(和可能的其他服务器端语言)具有在烘烤可以采取请求的数据看起来像的阵列(它)逻辑,并把它一起作为一个阵列在填充$_GET$_POST

例如,当你从一个表单POST数组,表单元素往往是这个样子:

<form ...> 
    <input name="my_array[0]"> 
    <input name="my_array[1]"> 
    <input name="my_array[2]"> 
</form> 

甚至:

<form ...> 
    <input name="my_array[]"> 
    <input name="my_array[]"> 
    <input name="my_array[]"> 
</form> 

虽然PHP知道该怎么做与此数据当它收到它(即。构建一个数组),对于HTML和HTTP,你有三个不相关的输入,它们恰好有相似的(或者相同的,尽管这在技术上并不是有效的HTML)名称。

要为您的cURL请求做相反的处理,您需要将您的数组分解为键的字符串表示形式。因此,与您的name数组,你可以这样做:

foreach ($post['name'] as $id => $name) 
{ 
    $post['name[' . $id . ']'] = $name; 
} 
unset($post['name']); 

这将导致您的$post阵列看起来像:

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

然后你正在发布将是一个阵列中的每个关键标量的值,cURL期望的值,并且该数组将表示为您需要的HTTP。

+2

谢谢您的回答,它并没有完全回答这个问题,但它非常有见地! – 2010-09-24 10:06:11

+0

非常感谢! – 2011-10-02 15:26:03

0

我想你会需要通过选项字符串:

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

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

27
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); 
+1

非常有帮助,谢谢!如果你有嵌套数组并需要上传文件,你需要这样做 – fishbone 2012-02-10 19:08:57

+0

这对我来说很好。谢谢 – 2013-04-11 17:31:02

+2

我觉得这是更好的解决方案,因为它也可以轻松处理文件上传。谢谢! – Tominator 2014-03-13 08:27:16

-1
$post = "ac=on&p=1&pr[]=0&pr[]=1&a[]=3&a[]=4&pl=on&sp[]=3&ct[]=3&s=1&o=0&pp=3&sortBy=date"; 
parse_str($post,$fields); 

$url = 'http://example.com/'; 


//open connection 
$ch = curl_init(); 

//set the url, number of POST vars, POST data 
curl_setopt($ch,CURLOPT_URL, $url); 
curl_setopt($ch,CURLOPT_POST, true); 
curl_setopt($ch,CURLOPT_POSTFIELDS, $fields); 
curl_setopt($ch,CURLOPT_RETURNTRANSFER, true); 

//execute post 
$result = curl_exec($ch); 

//close connection 
curl_close($ch); 
13

简单的办法是做一个:

$array = urldecode(http_build_query($array)); 

下面就是这是在现实生活中使用的示例代码:

https://gist.github.com/gayanhewa/142c48162f72e68a4a23

当你嵌套$在上述要点params部分,它会相应地解析它,并准备通过卷曲进行发布。

0

cURL选项CURLOPT_POSTFIELDS将接受字符串或简单数组而不是嵌套数组。试图这样做会产生Array to string conversion错误。

但是http_build_query()可以处理一个嵌套数组,因此可以使用它将$_POST数组转换为字符串,然后发送该字符串。所以,你有什么;

curl_setopt($ch, CURLOPT_POSTFIELDS, $_POST); 

用这个代替;

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

首先,我要感谢丹尼尔Vandersluisinsightful reply。根据他的投入,我想出了这个解决从原来的问题的问题:

<?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; 
} 

用法应该是这样的:

curl_setopt($this->ch, CURLOPT_POSTFIELDS, curl_postfields_flatten($post)); 

此功能将转换数组是这样的:

array(
    'a' => 'a', 
    'b' => array(
    'c' => array(
     'd' => 'd', 
     'e' => array(
     'f' => 'f', 
    ), 
    ), 
), 
); 

进入这个:

array(
    'a' => 'a', 
    'b[c][d]' => 'd', 
    'b[c][e][f]' => 'f', 
) 

它不处理与混合格式的情况下,当有这样一个关键的碰撞:

array(
'b[c]' => '1', 
'b' => array(
    'c' => '2', 
), 
); 

输出将只包含第一个值该键

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