format curl POST pour CURLOPT_POSTFIELDS

99

Quand j'utilise curlvia POSTet set, CURLOPT_POSTFIELDdois-je utiliser urlencodeun format spécial?

par exemple: Si je veux publier 2 champs, premier et dernier:

first=John&last=Smith

quel est le code / format exact à utiliser avec curl?

$ch=curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$reply=curl_exec($ch);
curl_close($ch);
Ken
la source

Réponses:

100

Si vous envoyez une chaîne, urlencode (). Sinon, si tableau, il doit être key => value paired et l'en- Content-typetête est automatiquement défini sur multipart/form-data.

De plus, vous n'avez pas besoin de créer des fonctions supplémentaires pour créer la requête de vos tableaux, vous l'avez déjà:

$query = http_build_query($data, '', '&');
kodeart
la source
13
Vous pouvez simplement utiliser http_build_query($data)puisque &est le séparateur par défaut.
annulation du
6
Bien sûr, vous pouvez les ignorer. Ceci est pour illustrer les deux autres arguments que vous pouvez (ou non) modifier (ex. Le séparateur par défaut) pour répondre à vos besoins spécifiques.
kodeart
62

EDIT : À partir de php5, l'utilisation de http_build_queryest recommandée:

string http_build_query ( mixed $query_data [, string $numeric_prefix [, 
                          string $arg_separator [, int $enc_type = PHP_QUERY_RFC1738 ]]] )

Exemple simple du manuel:

<?php
$data = array('foo'=>'bar',
              'baz'=>'boom',
              'cow'=>'milk',
              'php'=>'hypertext processor');

echo http_build_query($data) . "\n";

/* output:
foo=bar&baz=boom&cow=milk&php=hypertext+processor
*/

?>

avant php5:

À partir du manuel :

CURLOPT_POSTFIELDS

Les données complètes à publier dans une opération HTTP "POST". Pour publier un fichier, ajoutez un nom de fichier avec @ et utilisez le chemin complet. Le type de fichier peut être spécifié explicitement en suivant le nom de fichier avec le type au format '; type = mimetype'. Ce paramètre peut être passé sous forme de chaîne codée par URL comme «para1 = val1 & para2 = val2 & ...» ou sous forme de tableau avec le nom du champ comme clé et les données de champ comme valeur. Si value est un tableau, l'en-tête Content-Type sera défini sur multipart / form-data. Depuis PHP 5.2.0, les fichiers passés à cette option avec le préfixe @ doivent être sous forme de tableau pour fonctionner.

Donc, quelque chose comme ça devrait fonctionner parfaitement (avec des paramètres passés dans un tableau associatif):

function preparePostFields($array) {
  $params = array();

  foreach ($array as $key => $value) {
    $params[] = $key . '=' . urlencode($value);
  }

  return implode('&', $params);
}
Czechnologie
la source
11
Pourquoi passeriez-vous une chaîne si vous pouvez passer un tableau ...?
ThiefMaster
1
Je pense que $ key devrait aussi être encodé, juste au cas où vous l'auriez comme "nom et prénom", etc. Surtout si les données sont fournies par l'utilisateur final
Marius Balčytis
2
@barius, je suis d'accord avec vous. Et je pense que http_build_query () est en fait meilleur que la fonction définie ci-dessus.
skyfree
1
@skyfree Je suis d'accord! Cette fonction a été ajoutée dans php5, ce qui était encore loin d'être standard en 2011.
Czechnology
1
pourquoi http_build_query est requis alors que vous pouvez simplement passer un tableau?
Offenso
39

Ne passez pas du tout une corde!

Vous pouvez passer un tableau et laisser php / curl faire le sale boulot d'encodage, etc.

ThiefMaster
la source
16
transmettre un tableau sera un type de contenu différent d'une chaîne, il y a donc une bonne raison de le faire. Il m'a fallu un certain temps pour comprendre cela.
Thomas Vander Stichele
Je ne sais pas pourquoi, mais je trouve que sur mon PC Win dev, le passage d'un tableau prend environ une seconde de plus (1,029s en utilisant un tableau contre 0,016s en utilisant http_build_query()ce même tableau)
kratenko
2
Les tableaux imbriqués ne fonctionneront pas. cURL essaiera de les convertir en chaîne et un avis de conversion de tableau PHP en chaîne suivra
7ochem
5

Selon le manuel PHP, les données passées à cURL sous forme de chaîne doivent être encodées en URL. Consultez la page curl_setopt () et recherchez CURLOPT_POSTFIELDS.

Rêves surréalistes
la source
4

Pour CURLOPT_POSTFIELDS, les paramètres peuvent être passés sous forme de chaîne codée par URL comme para1=val1&para2=val2&..ou sous forme de tableau avec le nom du champ comme clé et les données de champ comme valeur

Essayez le format suivant:

$data = json_encode(array(
"first"  => "John",
"last" => "Smith"
));

$ch = curl_init(); 
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$output = curl_exec($ch);
curl_close($ch);
Shraddha Vadnere
la source
2
Salut Shraddha, json_encode()vous donnera quelque chose de vraiment différent d'une chaîne de paramètres valide comme first=John&last=Smith. json_encode()produira: {"first":"John","last":"Smith"}qui deviendra alors le corps brut de votre requête POST.
7ochem
1
Pour ajouter au commentaire de @ 7ochem: À moins que le destinataire n'attende un seul paramètre contenant une chaîne codée en json , au lieu de json_encode(...)do http_build_query(...). Cela créera la "chaîne encodée par URL" attendue contenant les paramètres séparés par "&".
ToolmakerSteve
4

Une autre différence majeure qui n'est pas encore mentionnée ici est qu'elle CURLOPT_POSTFIELDSne peut pas gérer les tableaux imbriqués.

Si nous prenons le tableau imbriqué, ['a' => 1, 'b' => [2, 3, 4]]cela devrait être paramétré comme a=1&b[]=2&b[]=3&b[]=4(le [et ]sera / devrait être encodé en URL). Cela sera reconverti automatiquement en un tableau imbriqué à l'autre extrémité (en supposant ici que l'autre extrémité est également PHP).

Cela fonctionnera:

var_dump(http_build_query(['a' => 1, 'b' => [2, 3, 4]]));
// output: string(36) "a=1&b%5B0%5D=2&b%5B1%5D=3&b%5B2%5D=4"

Cela ne fonctionnera pas:

curl_setopt($ch, CURLOPT_POSTFIELDS, ['a' => 1, 'b' => [2, 3, 4]]);

Cela vous donnera un avis. L'exécution du code se poursuivra et votre point de terminaison recevra le paramètre bsous forme de chaîne "Array":

Avis PHP: Conversion de tableau en chaîne en ... en ligne ...

7ochem
la source
4

Cela dépend du content-type

url-encoded ou multipart / form-data

Pour envoyer des données de manière standard, comme le ferait un navigateur avec un formulaire, il suffit de passer un tableau associatif . Comme indiqué dans le manuel de PHP:

Ce paramètre peut être passé sous forme de chaîne codée par URL comme «para1 = val1 & para2 = val2 & ...» ou sous forme de tableau avec le nom du champ comme clé et les données de champ comme valeur. Si value est un tableau, l'en-tête Content-Type sera défini sur multipart / form-data.

Encodage JSON

Néanmoins, lors de la communication avec les API JSON, le contenu doit être encodé en JSON pour que l'API comprenne nos données POST.

Dans de tels cas, le contenu doit être explicitement encodé en JSON:

CURLOPT_POSTFIELDS => json_encode(['param1' => $param1, 'param2' => $param2]),

Lors de la communication en JSON, nous définissons également généralement les en accept- content-typetêtes en conséquence:

CURLOPT_HTTPHEADER => [
    'accept: application/json',
    'content-type: application/json'
]
Buzut
la source
2

pour les tableaux imbriqués, vous pouvez utiliser:

$data = [
  'name[0]' = 'value 1',
  'name[1]' = 'value 2',
  'name[2]' = 'value 3',
  'id' = 'value 4',
  ....
];
Maxim Rysevets
la source
0

Fait intéressant, la façon dont Postman effectue POST est une opération GET complète avec ces 2 options supplémentaires:

curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_POSTFIELDS, '');

Juste une autre façon, et cela fonctionne très bien.

Klompenrunner
la source
-3

Cette réponse m'a également pris une éternité à trouver. J'ai découvert que tout ce que vous avez à faire est de concaténer l'URL ('?' Après le nom et l'extension du fichier) avec la chaîne de requête encodée par URL. Il ne semble même pas que vous deviez définir les options POST cURL. Voir le faux exemple ci-dessous:

//create URL
$exampleURL = 'http://www.example.com/example.php?';

// create curl resource
$ch = curl_init(); 

// build URL-encoded query string
$data = http_build_query(
    array('first' => 'John', 'last' => 'Smith', '&'); // set url
curl_setopt($ch, CURLOPT_URL, $exampleURL . $data); 

// return the transfer as a string
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 

// $output contains the output string
$output = curl_exec($ch); 

// close curl resource to free up system resources <br/>
curl_close($ch);

Vous pouvez également utiliser file_get_contents():

// read entire webpage file into a string
$output = file_get_contents($exampleURL . $data);
user2512571
la source
9
Il semble que vous faites un GET plutôt qu'un POST.
grandnasty le