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.

user3379466
źródło
Żą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

Michał Gallovic
źródło
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;
user3379466
źródło
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>';
Frank Roth
źródło
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());
davykiash
źródło
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();
CharlieJade
źródło
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();
Yamen Ashraf
źródło
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

arcos.lwm
źródło
7
use GuzzleHttp\Client;

$client = new Client();

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

Zobacz Dokumenty .

Nurul Huda
źródło
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());
Tuncay Elvanağaç
źródło
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.

j boschiero
źródło
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('[email protected]', 'password', 'Digest'),)));

$url          = "https://api.yourbaseapiserver.com/incidents.xml";
        
$data = '<incident>
<name>Incident Title2a</name>
<priority>Medium</priority>
<requester><email>[email protected]</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('[email protected]', '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;
Łajno
źródło
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']));
Suraj
źródło
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();

źródło