curl POST format dla CURLOPT_POSTFIELDS


99

Kiedy używam curlvia POSTi set, CURLOPT_POSTFIELDczy muszę mieć urlencodejakiś specjalny format?

na przykład: Jeśli chcę opublikować 2 pola, pierwsze i ostatnie:

first=John&last=Smith

jaki jest dokładny kod / format, który powinien być używany z 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);

Odpowiedzi:


100

Jeśli wysyłasz ciąg, urlencode () go. W przeciwnym razie, jeśli tablica, powinna być sparowana klucz => wartość, a Content-typenagłówek jest automatycznie ustawiany na multipart/form-data.

Nie musisz też tworzyć dodatkowych funkcji, aby zbudować zapytanie dla swoich tablic, już to masz:

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

13
Możesz po prostu użyć, http_build_query($data)ponieważ &jest domyślnym separatorem.
— nieważność

6
Oczywiście możesz je pominąć. Ma to na celu zilustrowanie pozostałych dwóch argumentów, które możesz (lub nie) zmienić (np. Domyślny separator), aby dopasować się do swoich konkretnych potrzeb.
— kodeart

62

EDYCJA : Od php5 w górę http_build_queryzalecane jest użycie:

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

Prosty przykład z instrukcji:

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

?>

przed php5:

Z instrukcji :

CURLOPT_POSTFIELDS

Pełne dane do wysłania w operacji „POST” HTTP. Aby opublikować plik, poprzedź jego nazwę znakiem @ i użyj pełnej ścieżki. Typ pliku można jawnie określić, dodając po nazwie pliku typ w formacie „; type = mimetype”. Ten parametr można przekazać jako ciąg zakodowany jako urlen, taki jak „para1 = val1 & para2 = val2 & ...” lub jako tablicę z nazwą pola jako kluczem i danymi pola jako wartością. Jeśli wartość jest tablicą, nagłówek Content-Type zostanie ustawiony na multipart / form-data. Począwszy od PHP 5.2.0, pliki przekazywane do tej opcji z prefiksem @ muszą mieć postać tablicową, aby działały.

Więc coś takiego powinno działać idealnie (z parametrami przekazanymi w tablicy asocjacyjnej):

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

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

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

11
Dlaczego miałbyś przekazywać ciąg, skoro możesz przekazać tablicę ...?
— ThiefMaster

1
Myślę, że klucz $ również powinien być zakodowany, na wypadek gdybyś miał go w stylu "imię i nazwisko" itp. Zwłaszcza jeśli dane są podane przez użytkownika końcowego
— Marius Balčytis.

2
@barius, zgadzam się z tobą. I myślę, że http_build_query () faktycznie jest lepsze niż funkcja zdefiniowana powyżej.
— skyfree

1
@skyfree Zgadzam się! Ta funkcja została dodana w php5, co wciąż było dalekie od standardu w 2011.
— Czechnology

1
dlaczego http_build_query jest wymagane, skoro można po prostu przekazać tablicę?
— Offenso

39

W ogóle nie przekazuj ciągu!

Możesz przekazać tablicę i pozwolić php / curl wykonać brudną robotę kodowania itp.


16
przekazanie tablicy będzie innym typem zawartości niż ciąg, więc jest dobry powód, aby to zrobić. Zajęło mi trochę czasu, zanim to rozgryzłem.
— Thomas Vander Stichele

Nie mam pojęcia dlaczego, ale uważam, że na mój dev pc wygrana przekazywanie tablicy trwa około sekundy dłużej (1.029s wykorzystujące 0.016s tablicę vs. przy użyciu http_build_query()tego samego tablicy)
— kratenko

2
Tablice zagnieżdżone nie będą działać. cURL spróbuje przekonwertować je na ciągi znaków i nastąpi powiadomienie o konwersji tablicy PHP na ciąg
— 7ochem.

5

Zgodnie z instrukcją PHP dane przekazywane do cURL jako ciąg znaków powinny być zakodowane w postaci adresu URL. Zobacz stronę dotyczącą curl_setopt () i wyszukaj CURLOPT_POSTFIELDS.


4

W CURLOPT_POSTFIELDSprzypadku parametrów można przekazywać jako ciąg znaków z kodem urlen, na przykład para1=val1&para2=val2&..jako tablicę z nazwą pola jako kluczem i danymi pola jako wartością

Wypróbuj następujący format:

$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
Cześć Shraddha, json_encode()da ci coś naprawdę innego od prawidłowego ciągu parametrów jako first=John&last=Smith. json_encode()wyświetli: {"first":"John","last":"Smith"}które następnie stanie się surową treścią twojego żądania POST.
— 7ochem

1
Aby dodać do komentarza @ 7ochem: Chyba że odbiorca oczekuje pojedynczego parametru zawierającego ciąg zakodowany w formacie JSON zamiast json_encode(...)do http_build_query(...). Spowoduje to utworzenie oczekiwanego „ciągu zakodowanego w adresie URL” zawierającego parametry oddzielone znakiem „&”.
— ToolmakerSteve

4

Inną ważną różnicą, o której jeszcze nie wspomniano, jest CURLOPT_POSTFIELDSbrak obsługi tablic zagnieżdżonych.

Jeśli weźmiemy zagnieżdżoną tablicę, ['a' => 1, 'b' => [2, 3, 4]]należy ją sparametryzować jako a=1&b[]=2&b[]=3&b[]=4( [i ]będzie / powinno być zakodowane w postaci adresu URL). Zostanie to automatycznie przekonwertowane z powrotem na zagnieżdżoną tablicę na drugim końcu (zakładając, że drugi koniec to również PHP).

To zadziała:

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"

To nie zadziała:

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

To da ci ostrzeżenie. Wykonywanie kodu będzie kontynuowane, a punkt końcowy otrzyma parametr w bpostaci ciągu "Array":

Uwaga PHP: konwersja tablicy na ciąg w ... on-line ...


4

To zależy od content-type

url-encoded lub multipart / form-data

Aby wysłać dane w standardowy sposób, tak jak robiłaby to przeglądarka z formularzem, wystarczy przekazać tablicę asocjacyjną . Jak stwierdzono w podręczniku PHP:

Ten parametr można przekazać jako ciąg zakodowany jako urlen, taki jak „para1 = val1 & para2 = val2 & ...”, lub jako tablicę z nazwą pola jako kluczem i danymi pola jako wartością. Jeśli wartość jest tablicą, nagłówek Content-Type zostanie ustawiony na multipart / form-data.

Kodowanie JSON

Niemniej jednak podczas komunikacji z interfejsami API JSON zawartość musi być zakodowana w formacie JSON, aby interfejs API mógł zrozumieć nasze dane POST.

W takich przypadkach treść musi być wyraźnie zakodowana w formacie JSON:

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

Podczas komunikacji w JSON, również zazwyczaj ustawione accepti content-typenagłówki odpowiednio:

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

2

w przypadku tablic zagnieżdżonych możesz użyć:

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

0

Co ciekawe, sposób, w jaki Postman wykonuje POST, to kompletna operacja GET z dwoma dodatkowymi opcjami:

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

Po prostu inny sposób i działa bardzo dobrze.


-3

Ta odpowiedź również zajęła mi wieczność. Odkryłem, że wszystko, co musisz zrobić, to połączyć adres URL („?” Po nazwie pliku i rozszerzeniu) z ciągiem zapytania zakodowanym w adresie URL. Nawet nie wygląda na to, że musisz ustawić opcje POST cURL. Zobacz fałszywy przykład poniżej:

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

Możesz również użyć file_get_contents():

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

9
Wygląda na to, że robisz raczej GET niż POST.
— grandnasty
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.