formato POST curl per CURLOPT_POSTFIELDS


99

Quando uso curlvia POSTe set CURLOPT_POSTFIELDdevo farlourlencode o qualsiasi formato speciale?

ad esempio: se voglio inserire 2 campi, primo e ultimo:

first=John&last=Smith

qual è il codice / formato esatto che dovrebbe essere usato con 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);

Risposte:


100

Nel caso in cui invii una stringa, urlencode () it. Altrimenti, se array, dovrebbe essere key => value accoppiato e l' Content-typeintestazione viene automaticamente impostata sumultipart/form-data .

Inoltre, non devi creare funzioni extra per costruire la query per i tuoi array, lo hai già:

$query = http_build_query($data, '', '&');

13
Puoi semplicemente usare http_build_query($data)poiché &è il separatore predefinito.
nullability

6
Ovviamente puoi saltarli. Questo per illustrare gli altri due argomenti che puoi (o non puoi) modificare (es. Il separatore predefinito) per soddisfare le tue esigenze specifiche.
kodeart

62

EDIT : da php5 in poi, http_build_querysi consiglia di utilizzare:

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

Semplice esempio dal manuale:

<?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
*/

?>

prima di php5:

Dal manuale :

CURLOPT_POSTFIELDS

I dati completi da inserire in un'operazione "POST" HTTP. Per inserire un file, anteponi @ al nome di un file e utilizza il percorso completo. Il tipo di file può essere specificato esplicitamente seguendo il nome del file con il tipo nel formato "; type = mimetype". Questo parametro può essere passato come stringa codificata come "para1 = val1 & para2 = val2 & ..." o come array con il nome del campo come chiave e i dati del campo come valore. Se il valore è un array, l'intestazione Content-Type verrà impostata su multipart / form-data. A partire da PHP 5.2.0, i file passati a questa opzione con il prefisso @ devono essere in formato array per funzionare.

Quindi qualcosa di simile dovrebbe funzionare perfettamente (con i parametri passati in un array associativo):

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

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

  return implode('&', $params);
}

11
Perché dovresti passare una stringa se puoi passare un array ...?
ThiefMaster

1
Penso che anche $ key dovrebbe essere codificata, nel caso in cui sia come "nome e cognome" ecc. Specialmente se i dati sono forniti dall'utente finale
Marius Balčytis

2
@bario, sono d'accordo con te. E penso che http_build_query () sia effettivamente migliore della funzione definita sopra.
skyfree

1
@skyfree sono d'accordo! Questa funzione è stata aggiunta in php5, che era ancora lontana dallo standard nel 2011.
Czechnology,

1
perché http_build_query è richiesto quando potresti semplicemente passare array?
Offenso

39

Non passare affatto una stringa!

Puoi passare un array e lasciare che php / curl faccia il lavoro sporco di codifica, ecc.


16
passare un array sarà un tipo di contenuto diverso da una stringa, quindi c'è una buona ragione per farlo. Mi ci è voluto un po 'per capirlo.
Thomas Vander Stichele

Non ho idea del perché, ma trovo che sul mio pc win dev il passaggio di un array impiega circa un secondo in più (1.029s usando array vs 0.016s usando http_build_query()sullo stesso array)
kratenko

2
Gli array annidati non funzioneranno. cURL proverà a convertirli in stringa e seguirà un avviso di conversione da array PHP a stringa
7ochem

5

Secondo il manuale PHP, i dati passati a cURL come stringa dovrebbero essere codificati in URL. Vedi la pagina per curl_setopt () e cerca CURLOPT_POSTFIELDS.


4

Per CURLOPT_POSTFIELDS, i parametri possono essere passati come una stringa codificata come URL para1=val1&para2=val2&..o come un array con il nome del campo come chiave e i dati del campo come valore

Prova il seguente formato:

$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);

2
Ciao Shraddha, json_encode()ti darà qualcosa di veramente diverso da una stringa di parametri valida come first=John&last=Smith. json_encode()produrrà: {"first":"John","last":"Smith"}che diventerà quindi il corpo grezzo della tua richiesta POST.
7ochem

1
Per aggiungere al commento di @ 7ochem: A meno che il destinatario non si aspetti un singolo parametro contenente una stringa con codifica json , invece di json_encode(...)fare http_build_query(...). Questo creerà la "stringa codificata nell'URL" prevista contenente i parametri separati da "&".
ToolmakerSteve

4

Un'altra importante differenza che non è stata ancora menzionata qui è che CURLOPT_POSTFIELDSnon può gestire array annidati.

Se prendiamo l'array annidato, ['a' => 1, 'b' => [2, 3, 4]]questo dovrebbe essere parametrizzato come a=1&b[]=2&b[]=3&b[]=4( [e ]sarà / dovrebbe essere codificato in URL). Questo verrà riconvertito automaticamente in un array annidato all'altra estremità (supponendo che anche l'altra estremità sia PHP).

Questo funzionerà:

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"

Questo non funzionerà:

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

Questo ti darà un avviso. L'esecuzione del codice continuerà e il tuo endpoint riceverà il parametro bcome stringa "Array":

Avviso PHP: conversione da array a stringa in ... in linea ...


4

Dipende da content-type

con codifica URL o multipart / form-data

Per inviare i dati nel modo standard, come farebbe un browser con un modulo, è sufficiente passare un array associativo . Come affermato dal manuale di PHP:

Questo parametro può essere passato come stringa codificata come "para1 = val1 & para2 = val2 & ..." o come array con il nome del campo come chiave e i dati del campo come valore. Se il valore è un array, l'intestazione Content-Type verrà impostata su multipart / form-data.

Codifica JSON

Tuttavia, quando si comunica con le API JSON, il contenuto deve essere codificato in JSON affinché l'API possa comprendere i nostri dati POST.

In questi casi, il contenuto deve essere codificato esplicitamente come JSON:

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

Quando si comunica in JSON, di solito impostiamo anche le intestazioni accepte di content-typeconseguenza:

CURLOPT_HTTPHEADER => [
    'accept: application/json',
    'content-type: application/json'
]

2

per gli array annidati puoi usare:

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

0

È interessante notare che il modo in cui Postman esegue il POST è un'operazione GET completa con queste 2 opzioni aggiuntive:

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

Solo un altro modo e funziona molto bene.


-3

Anche questa risposta mi ci è voluta un'eternità per trovare. Ho scoperto che tutto ciò che devi fare è concatenare l'URL ("?" Dopo il nome del file e l'estensione) con la stringa di query con codifica URL. Non sembra nemmeno che tu debba impostare le opzioni POST cURL. Guarda il falso esempio di seguito:

//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);

Puoi anche usare file_get_contents():

// read entire webpage file into a string
$output = file_get_contents($exampleURL . $data);

9
Sembra che tu stia facendo un GET piuttosto che un POST.
grandnasty
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.