《Guzzle 5.3》前情提要:
$response = $client->get('http://httpbin.org/get');
$array = $response->json(); // Yoohoo
var_dump($array[0]['origin']);
我可以很容易地从JSON响应中获得PHP数组。现在在《狂饮6》中,我不知道该怎么做。似乎再也没有json()
方法了。我(快速)阅读了最新版本的文档,没有发现任何关于JSON响应的内容。我想我错过了一些东西,也许有一个新概念我不理解(或者我没有读对)。
这(下面)新方法是唯一的方法吗?
$response = $client->get('http://httpbin.org/get');
$array = json_decode($response->getBody()->getContents(), true); // :'(
var_dump($array[0]['origin']);
或者有一个助手之类的东西?
我现在用json_decode($response->getBody())
代替$response->json()
。
我怀疑这可能是PSR-7遵从性的牺牲品。
切换到:
json_decode($response->getBody(), true)
如果您希望它完全像以前一样工作,以获得数组而不是对象,则不使用其他注释
我使用$response->getBody()->getContents()
从响应中获取JSON。Guzzle version 6.3.0
如果你们仍然感兴趣,这里是我基于Guzzle中间件特性的解决方案:
-
创建
JsonAwaraResponse
,将解码JSON响应Content-Type
HTTP头,如果没有-它将作为标准的Guzzle响应:<?php namespace GuzzleHttpPsr7; class JsonAwareResponse extends Response { /** * Cache for performance * @var array */ private $json; public function getBody() { if ($this->json) { return $this->json; } // get parent Body stream $body = parent::getBody(); // if JSON HTTP header detected - then decode if (false !== strpos($this->getHeaderLine('Content-Type'), 'application/json')) { return $this->json = json_decode($body, true); } return $body; } }
-
创建中间件,用上述响应实现取代Guzzle PSR-7响应:
<?php $client = new GuzzleHttpClient(); /** @var HandlerStack $handler */ $handler = $client->getConfig('handler'); $handler->push(GuzzleHttpMiddleware::mapResponse(function (PsrHttpMessageResponseInterface $response) { return new GuzzleHttpPsr7JsonAwareResponse( $response->getStatusCode(), $response->getHeaders(), $response->getBody(), $response->getProtocolVersion(), $response->getReasonPhrase() ); }), 'json_decode_middleware');
在此之后检索JSON作为PHP原生数组使用Guzzle一如既往:
$jsonArray = $client->get('http://httpbin.org/headers')->getBody();
测试与guzzlehttp/guzzle 6.3.3
$response
是PSR-7 ResponseInterface
的实例。详细信息请参见https://www.php-fig.org/psr/psr-7/#3-interfaces
getBody()
返回StreamInterface
:
/**
* Gets the body of the message.
*
* @return StreamInterface Returns the body as a stream.
*/
public function getBody();
StreamInterface
实现__toString()
将流中的所有数据从头到尾读入字符串。
因此,要将body读取为string,必须将其强制转换为string:
$stringBody = $response->getBody()->__toString()
陷阱
-
json_decode($response->getBody()
不是最好的解决方案,因为它神奇地将流转换为字符串。json_decode()
要求字符串作为第一个参数。 不要使用
$response->getBody()->getContents()
,除非你知道你在做什么。如果你阅读getContents()
的文档,它说:Returns the remaining contents in a string
。因此,调用getContents()
读取流的其余部分,并且再次调用它不会返回任何内容,因为流已经在末尾。你必须在这些呼叫之间倒带流。添加->getContents()
不返回jSON响应,而是作为文本返回。
可以直接使用json_decode