DEV Community

Recca Tsai
Recca Tsai

Posted on • Originally published at recca0120.github.io

GuzzleHttp getContents() Returns Empty on the Second Call

Originally published at recca0120.github.io

Two Ways to Get the Body

After getting a Response from GuzzleHttp PSR-7, there are two ways to retrieve the content:

// Method 1: Cast to string
(string) $response->getBody();

// Method 2: getContents()
$response->getBody()->getContents();
Enter fullscreen mode Exit fullscreen mode

On the first call, both return the same result. But calling them twice reveals a difference.

The Difference

// Method 1: Both calls return content
(string) $response->getBody(); // has content
(string) $response->getBody(); // has content

// Method 2: Second call returns empty
$response->getBody()->getContents(); // has content
$response->getBody()->getContents(); // empty string
Enter fullscreen mode Exit fullscreen mode

Why

Looking at the source code makes it clear. __toString calls seek(0) to reset the stream pointer, so casting to string always reads the full content:

class Stream implements StreamInterface
{
    public function __toString()
    {
        try {
            $this->seek(0); // Reset pointer
            return (string) stream_get_contents($this->stream);
        } catch (\Exception $e) {
            return '';
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

getContents() does not reset the pointer -- it reads from the current position forward. After the first read, the pointer is at the end, so the second read returns nothing.

If you need to use getContents() and read multiple times, call $response->getBody()->rewind() first.

Top comments (0)