Jak mogę użyć Guzzle do wysłania żądania POST w JSON?


180

Czy ktoś wie, jak prawidłowo postużywać JSON Guzzle?

$request = $this->client->post(self::URL_REGISTER,array(
                'content-type' => 'application/json'
        ),array(json_encode($_POST)));

Otrzymuję internal server errorodpowiedź z serwera. Działa przy użyciu przeglądarki Chrome Postman.


Żądanie wydaje się być w porządku ... czy sprawdziłeś zawartość $ _POST, aby upewnić się, że naprawdę otrzymujesz wartości przed ich zakodowaniem? : var_dump ($ _ POST)
ylerjen

Zgodnie z dokumentacją możesz teraz po prostu użyć tego, co powiedział @davykiash 'json' => $data: stackoverflow.com/a/44154428/842768
giovannipds

Odpowiedzi:


262

W przypadku Guzzle 5, 6 i 7 robisz to tak:

use GuzzleHttp\Client;

$client = new Client();

$response = $client->post('url', [
    GuzzleHttp\RequestOptions::JSON => ['foo' => 'bar'] // or 'json' => [...]
]);

Dokumenty


13
To jest właściwy sposób ( oficjalny przykład tutaj )
Pierre de LESPINAY

5
Zaleca się stosowanie RequestOptionsstałych dla kluczy tablicy opcji ( GuzzleHttp\RequestOptions::JSONw tym przypadku) - ułatwia to wykrycie literówek, ponieważ nagle stają się powiadomieniami, a nie tylko cichymi błędami czekającymi na kłopoty.
ksadowski

7
@MichalGallovic To jest to samo. Celem użycia stałej jest uniknięcie literówek. Użycie stałej, która nie istnieje, spowoduje błąd, ale wysłanie bezużytecznej opcji (jak jssonna przykład) nie spowoduje żadnego błędu, a znalezienie literówki może zająć trochę czasu.
zessx

1
Szukałem tej odpowiedzi przez godzinę. Dlaczego nie ma tego w dokumentacji (zwłaszcza w podręczniku szybkiej konfiguracji)? Zwariowany!?!
Sevenearths

1
@giovannipds GuzzleHttp \ RequestOptions :: JSON jest aliasem do „json”, albo jest w porządku.
Michal Gallovic

44

Dla Guzzle <= 4 :

Jest to surowe żądanie posta, więc umieszczenie JSON w treści rozwiązało problem

$request = $this->client->post($url,array(
                'content-type' => 'application/json'
        ),array());
$request->setBody($data); #set body!
$response = $request->send();

return $response;

8
To już nie działa z GuzzleHttp. @Charlie ma właściwą odpowiedź
hbt

Myślę, że w pytaniu musimy tylko określić wersję Guzzle.
Fabrice Kabongo,

1
Jeśli chcesz ustawić typ zawartości nagłówka w chlać 6, można to zrobić tak:$client->post($url, ['body' => $string, 'headers' => ['Content-type' => 'application/json']]);
marcovtwout

Próbowałem tego z Guzzle3 nie działa, nawet jeśli jest to sposób wspomniany w dokumencie: guzzle3.readthedocs.io/http-client/ ... , minęły 2 dni próbuję rozwiązać ten plik pb, ale na próżno
Hanane

Zgodnie z dokumentacją możesz teraz po prostu użyć tego, co powiedział @davykiash 'json' => $data: stackoverflow.com/a/44154428/842768
giovannipds

42

Prosty i podstawowy sposób (guzzle6):

$client = new Client([
    'headers' => [ 'Content-Type' => 'application/json' ]
]);

$response = $client->post('http://api.com/CheckItOutNow',
    ['body' => json_encode(
        [
            'hello' => 'World'
        ]
    )]
);

Aby uzyskać kod stanu odpowiedzi i zawartość treści, zrobiłem to:

echo '<pre>' . var_export($response->getStatusCode(), true) . '</pre>';
echo '<pre>' . var_export($response->getBody()->getContents(), true) . '</pre>';

2
To naprawdę jeden prosty i łatwy sposób. Rozwiązano mój problem z ustawieniem treści i nagłówków. Bardzo dziękuję
Faisal Sarfraz

Ta odpowiedź działa dla mnie, gdy zaakceptowana odpowiedź nie.
vietnguyen09

32

To zadziałało dla mnie (używając Guzzle 6)

$client = new Client(); 
$result = $client->post('http://api.example.com', [
            'json' => [
                'value_1' => 'number1',
                'Value_group' =>  
                             array("value_2" => "number2",
                                    "value_3" => "number3")
                    ]
                ]);

echo($result->getBody()->getContents());

25
$client = new \GuzzleHttp\Client();

$body['grant_type'] = "client_credentials";
$body['client_id'] = $this->client_id;
$body['client_secret'] = $this->client_secret;

$res = $client->post($url, [ 'body' => json_encode($body) ]);

$code = $res->getStatusCode();
$result = $res->json();

2
Czy to również ustawia prawidłowy nagłówek? Myślę, że tutaj ['json' => $body]jest lepszy sposób, o czym wspomina odpowiedź Michaela.
Ja͢ck

1
$res->json();działa tylko w Guzzle 5.3. Został usunięty w wersji 6.
David

1
David ma rację. Wynika to z implementacji PSR-7. Użyj json_decode()zamiast tego.
Andreas

10
$client = new \GuzzleHttp\Client(['base_uri' => 'http://example.com/api']);

$response = $client->post('/save', [
    'json' => [
        'name' => 'John Doe'
    ]
]);

return $response->getBody();

8

To działa dla mnie z Guzzle 6.2:

$gClient =  new \GuzzleHttp\Client(['base_uri' => 'www.foo.bar']);
$res = $gClient->post('ws/endpoint',
                            array(
                                'headers'=>array('Content-Type'=>'application/json'),
                                'json'=>array('someData'=>'xxxxx','moreData'=>'zzzzzzz')
                                )
                    );

Zgodnie z dokumentacją guzzle wykonaj plik json_encode


7
use GuzzleHttp\Client;

$client = new Client();

$response = $client->post('url', [
    'json' => ['foo' => 'bar']
]);

Zobacz Dokumenty .


2

Wersja php: 5.6.0

Wersja Symfony: 2.3

Guzzle: 5.0

Niedawno miałem doświadczenie z wysyłaniem jsonów za pomocą Guzzle. Używam Symfony 2.3, więc moja wersja guzzle może być trochę starsza.

Pokażę również, jak korzystać z trybu debugowania i możesz zobaczyć żądanie przed wysłaniem,

Kiedy złożyłem żądanie, jak pokazano poniżej, otrzymałem pomyślną odpowiedź;

use GuzzleHttp\Client;

$headers = [
        'Authorization' => 'Bearer ' . $token,        
        'Accept'        => 'application/json',
        "Content-Type"  => "application/json"
    ];        

    $body = json_encode($requestBody);

    $client = new Client();    

    $client->setDefaultOption('headers', $headers);
    $client->setDefaultOption('verify', false);
    $client->setDefaultOption('debug', true);

    $response = $client->post($endPoint, array('body'=> $body));

    dump($response->getBody()->getContents());

0

Odpowiedź od użytkownika @ user3379466 może działać, ustawiając $dataw następujący sposób:

$data = "{'some_key' : 'some_value'}";

Nasz projekt wymagał wstawienia zmiennej do tablicy wewnątrz łańcucha json, co zrobiłem w następujący sposób (na wypadek, gdyby to komuś pomogło):

$data = "{\"collection\" : [$existing_variable]}";

Tak więc $existing_variablebędąc, powiedzmy, 90210, otrzymujesz:

echo $data;
//{"collection" : [90210]}

Warto również zauważyć, że możesz również chcieć ustawić 'Accept' => 'application/json'również na wypadek, gdyby punkt końcowy, w który trafiłeś, dba o tego typu rzeczy.


Tylko $datajson_encode$data = json_encode(array('collection' => $existing_variable));
uwaga

0

@ user3379466 jest poprawne, ale tutaj przepisuję w całości:

-package that you need:

 "require": {
    "php"  : ">=5.3.9",
    "guzzlehttp/guzzle": "^3.8"
},

-php code (Digest is a type so pick different type if you need to, i have to include api server for authentication in this paragraph, some does not need to authenticate. If you use json you will need to replace any text 'xml' with 'json' and the data below should be a json string too):

$client = new Client('https://api.yourbaseapiserver.com/incidents.xml', array('version' => 'v1.3', 'request.options' => array('headers' => array('Accept' => 'application/vnd.yourbaseapiserver.v1.1+xml', 'Content-Type' => 'text/xml'), 'auth' => array('username@gmail.com', 'password', 'Digest'),)));

$url          = "https://api.yourbaseapiserver.com/incidents.xml";
        
$data = '<incident>
<name>Incident Title2a</name>
<priority>Medium</priority>
<requester><email>dsss@mail.ca</email></requester>
<description>description2a</description>
</incident>';

    $request = $client->post($url, array('content-type' => 'application/xml',));

    $request->setBody($data); #set body! this is body of request object and not a body field in the header section so don't be confused.

    $response = $request->send(); #you must do send() method!
    echo $response->getBody(); #you should see the response body from the server on success
    die;

--- Rozwiązanie dla * Guzzle 6 * --- - pakiet, którego potrzebujesz:

 "require": {
    "php"  : ">=5.5.0",
    "guzzlehttp/guzzle": "~6.0"
},

$client = new Client([
                             // Base URI is used with relative requests
                             'base_uri' => 'https://api.compay.com/',
                             // You can set any number of default request options.
                             'timeout'  => 3.0,
                             'auth'     => array('you@gmail.ca', 'dsfddfdfpassword', 'Digest'),
                             'headers' => array('Accept'        => 'application/vnd.comay.v1.1+xml',
                                                'Content-Type'  => 'text/xml'),
                         ]);

$url = "https://api.compay.com/cases.xml";
    $data string variable is defined same as above.


    // Provide the body as a string.
    $r = $client->request('POST', $url, [
        'body' => $data
    ]);

    echo $r->getBody();
    die;

Dziękuję Ci. Nie mogłem znaleźć żadnego rozwiązania guzzle3 nigdzie indziej dla starszych projektów php5.3, chciałbym zobaczyć, jak podział linii chciałby również twojego guzzle6, ponieważ zaoszczędziłoby mi to dużo czasu.
taur

0

Powyższe odpowiedzi jakoś mi nie pomogły. Ale to działa dobrze dla mnie.

 $client = new Client('' . $appUrl['scheme'] . '://' . $appUrl['host'] . '' . $appUrl['path']);

 $request = $client->post($base_url, array('content-type' => 'application/json'), json_encode($appUrl['query']));

0

Po prostu użyj tego, to zadziała

   $auth = base64_encode('user:'.config('mailchimp.api_key'));
    //API URL
    $urll = "https://".config('mailchimp.data_center').".api.mailchimp.com/3.0/batches";
    //API authentication Header
    $headers = array(
        'Accept'     => 'application/json',
        'Authorization' => 'Basic '.$auth
    );
    $client = new Client();
    $req_Memeber = new Request('POST', $urll, $headers, $userlist);
    // promise
    $promise = $client->sendAsync($req_Memeber)->then(function ($res){
            echo "Synched";
        });
      $promise->wait();
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.