2010-09-22 56 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' 
)