Comment puis-je utiliser Guzzle pour envoyer une requête POST en JSON?


180

Quelqu'un connaît-il la bonne façon d' postutiliser JSON Guzzle?

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

Je reçois une internal server errorréponse du serveur. Cela fonctionne avec Chrome Postman.


La requête semble correcte ... avez-vous vérifié le contenu de $ _POST pour être sûr que vous obtenez vraiment les valeurs avant de les encoder? : var_dump ($ _ POST)
ylerjen

Selon la documentation maintenant, vous pouvez simplement utiliser ce que @davykiash a dit 'json' => $data: stackoverflow.com/a/44154428/842768
giovannipds

Réponses:


262

Pour Guzzle 5 et 6, procédez comme suit :

use GuzzleHttp\Client;

$client = new Client();

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

Docs


13
C'est la bonne façon de faire ( exemple officiel ici )
Pierre de LESPINAY

5
Il est recommandé d'utiliser des RequestOptionsconstantes pour les touches du tableau d'options ( GuzzleHttp\RequestOptions::JSONdans ce cas) - cela rend les fautes de frappe plus faciles à détecter car elles deviennent soudainement des notifications au lieu de simplement des bogues silencieux attendant de causer des problèmes.
ksadowski

7
@MichalGallovic C'est pareil. Le but d'utiliser la constante est d'éviter les fautes de frappe. L'utilisation d'une constante qui n'existe pas soulèvera une erreur, mais l'envoi d'une option inutile (comme jssonpar exemple) ne lèvera aucune erreur, et vous pourriez prendre un certain temps pour trouver votre faute de frappe.
zessx

1
Je cherchais cette réponse pendant une heure. Pourquoi ce n'est pas dans la documentation (en particulier le guide d'installation rapide)? Fou!?!
Sevenearths

1
@giovannipds GuzzleHttp \ RequestOptions :: JSON est un alias de 'json', non plus.
Michal Gallovic

44

Pour Guzzle <= 4 :

C'est une demande de publication brute, donc mettre le JSON dans le corps a résolu le problème

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

return $response;

8
Cela ne fonctionne plus avec GuzzleHttp. @Charlie a la bonne réponse
hbt

Je pense que nous devons simplement spécifier la version de Guzzle dans la question.
Fabrice Kabongo

1
Si vous souhaitez définir l'en-tête du type de contenu dans Guzzle 6, vous pouvez le faire comme ceci:$client->post($url, ['body' => $string, 'headers' => ['Content-type' => 'application/json']]);
marcovtwout

J'ai essayé cela avec Guzzle3 ne fonctionne pas même si c'est la manière mentionnée dans la doc: guzzle3.readthedocs.io/http-client / ... , ça fait 2 jours que j'essaye de résoudre ce pb mais en vain
Hanane

Selon la documentation maintenant, vous pouvez simplement utiliser ce que @davykiash a dit 'json' => $data: stackoverflow.com/a/44154428/842768
giovannipds

42

La manière simple et basique (guzzle6):

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

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

Pour obtenir le code d'état de la réponse et le contenu du corps, j'ai fait ceci:

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

2
C'est vraiment un moyen simple et facile. J'ai résolu mon problème de définition du corps et des en-têtes. Merci beaucoup
Faisal Sarfraz

Cette réponse fonctionne pour moi lorsque la réponse acceptée ne fonctionne pas.
vietnguyen09

32

Cela a fonctionné pour moi (en utilisant 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
Cela définit-il également l'en-tête correct? Je pense que ['json' => $body]c'est le meilleur moyen ici, comme le mentionne la réponse de Michael.
Ja͢ck

1
$res->json();ne fonctionne que dans Guzzle 5.3. Il a été supprimé dans la v6.
David

1
David a raison. Ceci est dû à la mise en œuvre du PSR-7. Utilisez json_decode()plutôt.
Andreas

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

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

return $response->getBody();

8

Cela fonctionne pour moi avec 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')
                                )
                    );

Selon la documentation guzzle, faites le json_encode


7
use GuzzleHttp\Client;

$client = new Client();

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

Voir la documentation .


2

Version Php: 5.6

Version de Symfony: 2.3

Guzzle: 5,0

J'ai récemment eu une expérience d'envoi de json avec Guzzle. J'utilise Symfony 2.3 donc ma version guzzle peut être un peu plus ancienne.

Je vais également montrer comment utiliser le mode débogage et vous pouvez voir la demande avant de l'envoyer,

Quand j'ai fait la demande comme indiqué ci-dessous j'ai obtenu la réponse réussie;

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

La réponse de @ user3379466 peut être mise en œuvre en définissant $datacomme suit:

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

Ce dont notre projet avait besoin était d'insérer une variable dans un tableau à l'intérieur de la chaîne json, ce que j'ai fait comme suit (au cas où cela aiderait quelqu'un):

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

Donc, en $existing_variableétant, disons, 90210, vous obtenez:

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

Il convient également de noter que vous voudrez peut-être également définir le 'Accept' => 'application/json'si le point de terminaison que vous touchez se soucie de ce genre de chose.


Juste un $datajson_encode$data = json_encode(array('collection' => $existing_variable));
avertissement

0

@ user3379466 est correct, mais ici je réécris en entier:

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

--- Solution pour * Guzzle 6 * --- -package dont vous avez besoin:

 "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;

Je vous remercie. Je n'ai trouvé aucune solution guzzle3 nulle part ailleurs pour les projets php5.3 hérités, j'aimerais le voir saut de ligne comme votre guzzle6 car cela m'aurait fait gagner beaucoup de temps.
taur

0

Les réponses ci-dessus n'ont pas fonctionné pour moi d'une manière ou d'une autre. Mais cela fonctionne bien pour moi.

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

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

0

Utilisez simplement ceci, cela fonctionnera

   $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();
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.