Guzzlehttp - Як отримати тіло відповіді від Guzzle 6?


163

Я намагаюся написати обгортку навколо апі, яку розвиває моя компанія. Це спокійно, і за допомогою Postman я можу надсилати запит на пошту до кінцевої точки, наприклад, http://subdomain.dev.myapi.com/api/v1/auth/з ім'ям користувача та паролем як дані POST, і мені повертається маркер. Всі роботи, як очікувалося. Тепер, коли я намагаюся зробити те ж саме з PHP, я повертаю GuzzleHttp\Psr7\Responseоб’єкт, але не можу знайти маркер де-небудь всередині нього, як я це робив із запитом листоноші.

Відповідний код виглядає так:

$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...

Вихід коду вище виглядає приблизно так (попередження, стінка тексту, що надходить):

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) {
    }
  }
}

Вихід від Postman був чимось на кшталт:

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

Зрозуміло, мені щось не вистачає щодо роботи з об'єктами відповіді в Guzzle. Відповідь Guzzle вказує на код запиту статус 200, тому я не впевнений, що саме потрібно зробити, щоб отримати повернені дані.


33
$response->getBody()->getContents()не працює?
Федеркун

Відповіді:


437

Guzzle реалізує PSR-7 . Це означає, що воно за замовчуванням зберігає тіло повідомлення в потоці, який використовує тимчасові потоки PHP. Щоб отримати всі дані, ви можете скористатися оператором кастингу:

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

Ви також можете це зробити

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

Різниця між двома підходами полягає в тому, що getContentsповертається решта вмісту, так що другий виклик нічого не повертає, якщо ви не шукаєте позицію потоку з rewindабо 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

Натомість, використовуючи операції лиття рядків PHP, він буде читати всі дані з потоку від початку до кінця.

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

Документація: http://docs.guzzlephp.org/en/latest/psr7.html#responses


5
Функція getContents є лише в одній невеликій частині документації Guzzle 6 (у розділі потоків), і я її пропустив. Ти врятував мене від безлічі пошуків.
Максим

58
СПАСИБІ. Неймовірно, що це не є більш зрозумілим у документації. Навіть їх офіційна документація ( docs.guzzlephp.org/en/latest ) здається, що виклик $ res-> getBody () повертає те, що ви зазвичай очікували.
Іоанн

24
Вони справді повинні помістити щось подібне до примітки чи повідомлення в офіційних документах. Я витратив на це питання два дні.
cwhsu

+1 Документація Guzzle помилково стверджує, що "you can pass true to this method [getBody()] to retrieve the body as a string.". Це, здається, не працює для мене за допомогою Guzzle 6, але кастинг на рядок або використання getContents () працює.
Magnus W

8
Ви також можете використовувати json_decode. Наприклад, заверніть свою відповідь у json_decode($response, true);це поверне масив.
Сигон

13

Якщо ви очікуєте повернення JSON, найпростіший спосіб його отримати:

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

// OR

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

json_decode()автоматично відкине тіло string, тому не потрібно телефонувати getContents().


1
Чому на цю відповідь все більше уваги ??? Це саме те, що мені було потрібно. Дякую @MaskimIvanov
Eric McWinNEr

Це було і для мене найбільш простою і легкою справою. Спасибі
Алатор
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.