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.

user3379466
la source
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

Michal Gallovic
la source
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;
user3379466
la source
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>';
Frank Roth
la source
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());
Davykiash
la source
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
la source
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();
Yamen Ashraf
la source
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

arcos.lwm
la source
7
use GuzzleHttp\Client;

$client = new Client();

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

Voir la documentation .

Nurul Huda
la source
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());
Tuncay Elvanağaç
la source
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.

j boschiero
la source
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('[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;

--- 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('[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;
Bouse
la source
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']));
Suraj
la source
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();

la source