2010-09-22 17 views
41

Tengo problemas para publicar datos de formulario a través de CURL en un script PHP que se encuentra en un host diferente.Contabilización de matriz multidimensional con PHP y CURL

Me aparece un error Array to string conversion

Ésta es print_r de la matriz que lo pongo:

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

Esta es la línea que el error se produce en:

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

El tercer argumento debe ser una matriz porque necesito que el encabezado Content-Type se establezca en multipart/form-data ya que estoy enviando un archivo a través de esta misma matriz, por lo tanto, no puedo convertir la matriz a una cadena de consulta o usar http_build_query().

Además, no tengo acceso al código en el host receptor, así que no puedo serializar y deserializar la matriz.

estoy suponiendo que el valor de la clave nombre ser un array es la causa de este error, también estoy asumiendo que CURLOPT_POSTFIELDS no admite matrices multidimensionales. ¿Hay alguna otra forma de evitar esto o estoy condenado?

¡Gracias de antemano!

Respuesta

23

Habría que crear la cadena postal manualmente, en lugar de pasar toda la matriz en A continuación, puede anular de rizo de auto-eligió encabezado de contenido con:.

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

Serializar/JSON-ifying serían más fáciles , pero como dices, no tienes control sobre el receptor, por lo que tienes que hacer un poco de trabajo extra.

+4

Gracias! Realmente no sabía que podía hacer esto. Agregué 'CURLOPT_HTTPHEADER' y pasé mi matriz a' http_build_query() '. ¡Trabajo hecho! –

+0

Gracias por mencionar 'http_build_query()'. ¡Funcionó como un encanto para mí! – mccbala

+1

En mi caso, esto no funciona. El error es ** Advertencia: Falta el límite en datos POST multipart/form-data en Desconocido en la línea 0 **. Lo que funcionó para mí fue [esta publicación] (http://stackoverflow.com/a/8224117/1057527) de Khristenko Yura – machineaddict

27

El concepto de una matriz realmente no existe cuando se trata de solicitudes HTTP. PHP (y otros lenguajes del lado del servidor probables) tiene lógica al horno en que pueden tomar los datos de solicitud que se ve como un array (a él) y lo pone juntos como una matriz al rellenar $_GET, etc. $_POST

Por ejemplo , cuando expone una matriz de un formulario, los elementos de formulario menudo tienen el siguiente aspecto:

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

o incluso:

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

Mientras PHP sabe qué hacer con estos datos cuando lo recibe (es decir. construir una matriz), a HTML y HTTP, tiene tres entradas no relacionadas que simplemente tienen nombres similares (o el mismo, aunque no es HTML técnicamente válido).

Para hacer lo contrario para su solicitud cURL, necesita descomponer su matriz en representaciones de cadena de las teclas. Así, con la matriz de name, usted podría hacer algo como:

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

que daría lugar a la matriz $post mirando como:

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

Y luego cada tecla en la matriz envías sería un valor escalar, que está esperando cURL, y la matriz se representaría como lo necesita para HTTP.

+2

Gracias por su respuesta, no contestó la pregunta, pero fue muy perspicaz. –

+0

¡MUCHAS GRACIAS! –

0

creo que necesita para pasar las opciones como una cadena:

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

A continuación, debería ser capaz de establecer el encabezado de forma manual a través 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

muy útil, ¡gracias! Lo necesitará si tiene matrices anidadas y necesita cargar archivos – fishbone

+0

Esto funcionó muy bien para mí. Gracias –

+2

Siento que esta es la mejor solución, ya que maneja cargas de archivos fácilmente también. ¡Gracias! – Tominator

-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

solución más simple es hacer un:

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

A continuación se muestra el código de ejemplo donde esto se utiliza en la vida real:

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

Cuando haya anidado $ la sección de params en la esencia anterior lo analizará en consecuencia y lo preparará para publicar a través de curl.

0

La opción cURL CURLOPT_POSTFIELDS aceptará una cadena o una matriz simple pero no una matriz anidada. Intentar hacerlo generará el error Array to string conversion.

Sin embargo, http_build_query() puede manejar una matriz anidada así que úsela para convertir la matriz $_POST a una cadena y luego envíe esa cadena. Entonces donde tienes;

curl_setopt($ch, CURLOPT_POSTFIELDS, $_POST); 

utilice esto;

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

primer lugar me gustaría dar las gracias a Daniel Vandersluis por su insightful reply. Basado en su entrada se me ocurrió esto a solucionar el problema de la pregunta original:

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

Uso debería tener este aspecto:

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

Esta función convertirá matrices así:

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

En esto:

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

No maneja los casos con formato mixto cuando hay un choque clave de la siguiente manera:

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

La salida contendrá sólo el primer valor para esa tecla

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