Guzzlehttp - Comment obtenir le corps d'une réponse de Guzzle 6?

163

J'essaye d'écrire un wrapper autour d'une API que mon entreprise développe. C'est reposant, et en utilisant Postman, je peux envoyer une demande de publication à un point de terminaison comme http://subdomain.dev.myapi.com/api/v1/auth/avec un nom d'utilisateur et un mot de passe en tant que données POST et on me rend un jeton. Tout fonctionne comme prévu. Maintenant, quand j'essaie de faire la même chose à partir de PHP, je récupère un GuzzleHttp\Psr7\Responseobjet, mais je ne parviens pas à trouver le jeton n'importe où à l'intérieur comme je l'ai fait avec la requête Postman.

Le code correspondant ressemble à:

$client = new Client(['base_uri' => 'http://companysub.dev.myapi.com/']);
$response = $client->post('api/v1/auth/', [
    'form_params' => [
        'username' => $user,
        'password' => $password
    ]
]);

var_dump($response); //or $resonse->getBody(), etc...

La sortie du code ci-dessus ressemble à quelque chose comme (avertissement, mur de texte entrant):

object(guzzlehttp\psr7\response)#36 (6) {
  ["reasonphrase":"guzzlehttp\psr7\response":private]=>
  string(2) "ok"
  ["statuscode":"guzzlehttp\psr7\response":private]=>
  int(200)
  ["headers":"guzzlehttp\psr7\response":private]=>
  array(9) {
    ["connection"]=>
    array(1) {
      [0]=>
      string(10) "keep-alive"
    }
    ["server"]=>
    array(1) {
      [0]=>
      string(15) "gunicorn/19.3.0"
    }
    ["date"]=>
    array(1) {
      [0]=>
      string(29) "sat, 30 may 2015 17:22:41 gmt"
    }
    ["transfer-encoding"]=>
    array(1) {
      [0]=>
      string(7) "chunked"
    }
    ["content-type"]=>
    array(1) {
      [0]=>
      string(16) "application/json"
    }
    ["allow"]=>
    array(1) {
      [0]=>
      string(13) "post, options"
    }
    ["x-frame-options"]=>
    array(1) {
      [0]=>
      string(10) "sameorigin"
    }
    ["vary"]=>
    array(1) {
      [0]=>
      string(12) "cookie, host"
    }
    ["via"]=>
    array(1) {
      [0]=>
      string(9) "1.1 vegur"
    }
  }
  ["headerlines":"guzzlehttp\psr7\response":private]=>
  array(9) {
    ["connection"]=>
    array(1) {
      [0]=>
      string(10) "keep-alive"
    }
    ["server"]=>
    array(1) {
      [0]=>
      string(15) "gunicorn/19.3.0"
    }
    ["date"]=>
    array(1) {
      [0]=>
      string(29) "sat, 30 may 2015 17:22:41 gmt"
    }
    ["transfer-encoding"]=>
    array(1) {
      [0]=>
      string(7) "chunked"
    }
    ["content-type"]=>
    array(1) {
      [0]=>
      string(16) "application/json"
    }
    ["allow"]=>
    array(1) {
      [0]=>
      string(13) "post, options"
    }
    ["x-frame-options"]=>
    array(1) {
      [0]=>
      string(10) "sameorigin"
    }
    ["vary"]=>
    array(1) {
      [0]=>
      string(12) "cookie, host"
    }
    ["via"]=>
    array(1) {
      [0]=>
      string(9) "1.1 vegur"
    }
  }
  ["protocol":"guzzlehttp\psr7\response":private]=>
  string(3) "1.1"
  ["stream":"guzzlehttp\psr7\response":private]=>
  object(guzzlehttp\psr7\stream)#27 (7) {
    ["stream":"guzzlehttp\psr7\stream":private]=>
    resource(40) of type (stream)
    ["size":"guzzlehttp\psr7\stream":private]=>
    null
    ["seekable":"guzzlehttp\psr7\stream":private]=>
    bool(true)
    ["readable":"guzzlehttp\psr7\stream":private]=>
    bool(true)
    ["writable":"guzzlehttp\psr7\stream":private]=>
    bool(true)
    ["uri":"guzzlehttp\psr7\stream":private]=>
    string(10) "php://temp"
    ["custommetadata":"guzzlehttp\psr7\stream":private]=>
    array(0) {
    }
  }
}

La sortie de Postman était quelque chose comme:

{
    "data" : {
        "token" "fasdfasf-asfasdfasdf-sfasfasf"
    }
}

Il me manque clairement quelque chose sur le travail avec les objets de réponse dans Guzzle. La réponse Guzzle indique un code de statut 200 sur la demande, je ne suis donc pas sûr de ce que je dois faire pour récupérer les données renvoyées.

Greg
la source
33
$response->getBody()->getContents()ne fonctionne pas?
Federkun

Réponses:

437

Guzzle implémente le PSR-7 . Cela signifie qu'il stockera par défaut le corps d'un message dans un Stream qui utilise des flux temporaires PHP. Pour récupérer toutes les données, vous pouvez utiliser l'opérateur de diffusion:

$contents = (string) $response->getBody();

Vous pouvez également le faire avec

$contents = $response->getBody()->getContents();

La différence entre les deux approches est que getContentsrenvoie le contenu restant, de sorte qu'un deuxième appel ne renvoie rien à moins que vous ne cherchiez la position du flux avec rewindou seek.

$stream = $response->getBody();
$contents = $stream->getContents(); // returns all the contents
$contents = $stream->getContents(); // empty string
$stream->rewind(); // Seek to the beginning
$contents = $stream->getContents(); // returns all the contents

Au lieu de cela, en utilisant les opérations de conversion de chaînes de PHP, il lit toutes les données du flux du début jusqu'à la fin.

$contents = (string) $response->getBody(); // returns all the contents
$contents = (string) $response->getBody(); // returns all the contents

Documentation: http://docs.guzzlephp.org/en/latest/psr7.html#responses

Federkun
la source
5
La fonction getContents n'est que dans une petite partie de la documentation Guzzle 6 (dans la section streams), et je l'ai ratée. Vous m'avez sauvé de beaucoup de recherches.
Maximus le
58
MERCI. Il est incroyable que ce ne soit pas plus clair dans la documentation. Même leur documentation officielle ( docs.guzzlephp.org/en/latest ) donne l'impression que l'appel de $ res-> getBody () renvoie ce que vous attendez normalement.
John
24
Ils devraient vraiment mettre quelque chose comme une note ou un avis dans les documents officiels. J'ai perdu deux jours sur cette question.
cwhsu le
+1 La documentation Guzzle le déclare à tort "you can pass true to this method [getBody()] to retrieve the body as a string.". Cela ne semble pas fonctionner pour moi avec Guzzle 6, mais le cast en chaîne ou en utilisant getContents () fonctionne.
Magnus W
8
Vous pouvez également utiliser json_decode. Par exemple, enveloppez votre réponse dans json_decode($response, true);ceci renverra un tableau.
Sygon
13

Si vous attendez le retour de JSON, le moyen le plus simple de l'obtenir:

$data = json_decode($response->getBody()); // returns an object

// OR

$data = json_decode($response->getBody(), true); // returns an array

json_decode()lancera automatiquement le corps vers string, il n'est donc pas nécessaire d'appeler getContents().

Maksim Ivanov
la source
1
Pourquoi cette réponse ne retient-elle pas plus l'attention ??? C'est précisément ce dont j'avais besoin. Merci @MaskimIvanov
Eric McWinNEr
C'était aussi la chose la plus simple et la plus facile pour moi. Merci
Alator