Je ne parviens pas à envoyer des données de formulaire via CURL à un script PHP de destination situé sur un hôte différent.
Je reçois une erreur Array to string conversion
Ceci est print_r
du tableau que je poste:
Array
(
[name] => Array
(
[0] => Jason
[1] => Mary
[2] => Lucy
)
[id] => 12
[status] => local
[file] => @/test.txt
)
C'est la ligne sur laquelle l'erreur se produit:
curl_setopt($this->ch, CURLOPT_POSTFIELDS, $post);
Le troisième argument must doit être un tableau car j'ai besoin que l'en-tête Content-Type
soit défini sur multipart/form-data
car j'envoie un fichier via ce même tableau. Je ne peux donc pas convertir le tableau en chaîne de requête ni utiliser http_build_query()
.
De plus, je n'ai pas accès au code sur l'hôte destinataire, je ne peux donc pas sérialiser ni désérialiser la matrice.
Je suppose que la valeur de la clé name étant un tableau étant la cause de cette erreur, je suppose également que CURLOPT_POSTFIELDS
ne prend pas en charge les tableaux multidimensionnels. Y a-t-il un autre moyen de contourner cela ou suis-je condamné?
Merci d'avance!
Vous devez créer manuellement la chaîne POST, plutôt que de transmettre l'intégralité du tableau. Vous pouvez ensuite remplacer l'en-tête de contenu choisi par curl par:
curl_setopt($c, CURLOPT_HTTPHEADER, array("Content-type: multipart/form-data"));
Sérialiser/json-ifying serait plus facile, mais comme vous le dites, vous n’avez aucun contrôle sur le destinataire, vous avez donc un peu de travail supplémentaire à faire.
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);
La solution la plus simple est de faire un:
$array = urldecode(http_build_query($array));
Voici un exemple de code utilisé dans la vie réelle:
https://Gist.github.com/gayanhewa/142c48162f72e68a4a23
Lorsque vous avez imbriqué la section $ params dans le fichier Gist ci-dessus, elle est analysée en conséquence et préparée en vue de son affichage via curl.
J'aimerais tout d'abord remercier Daniel Vandersluis pour son réponse perspicace . Sur la base de sa contribution, je suis venu avec ceci pour résoudre le problème de la question initiale:
<?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;
}
L'utilisation devrait ressembler à ceci:
curl_setopt($this->ch, CURLOPT_POSTFIELDS, curl_postfields_flatten($post));
Cette fonction convertira les tableaux comme ceci:
array(
'a' => 'a',
'b' => array(
'c' => array(
'd' => 'd',
'e' => array(
'f' => 'f',
),
),
),
);
Dans ceci:
array(
'a' => 'a',
'b[c][d]' => 'd',
'b[c][e][f]' => 'f',
)
Il ne gère pas les cas avec un format mixte lorsqu'il y a une collision clé comme ceci:
array(
'b[c]' => '1',
'b' => array(
'c' => '2',
),
);
La sortie contiendra uniquement la première valeur pour cette clé
array(
'b[c]' => '1'
)
Je pense que vous aurez besoin de passer les options sous forme de chaîne:
curl_setopt($this->ch, CURLOPT_POSTFIELDS, 'name[]=Jason&name[]=Mary&name[]=Lucy...');
Vous devriez alors pouvoir définir l'en-tête manuellement via CURLOPT_HTTPHEADER.
L'option cURL CURLOPT_POSTFIELDS
acceptera une chaîne ou un tableau simple, mais pas un tableau imbriqué. Si vous tentez de le faire, l'erreur Array to string conversion
est générée.
Cependant, http_build_query()
peut gérer un tableau imbriqué, utilisez-le pour convertir le tableau $_POST
en chaîne puis envoyez-la à la place. Alors où tu as;
curl_setopt($ch, CURLOPT_POSTFIELDS, $_POST);
utilisez ceci à la place;
curl_setopt($ch, CURLOPT_POSTFIELDS, urldecode(http_build_query($_POST)));