Laravel学习笔记之Core Concepts in Guzzle Package——Stream(一)
说明:本文主要学习guzzlehttp/guzzle package
的使用,该package提供了一套发送HTTP请求API,就像phpunit package, mockery package, symfony package, monolog package, league/filesystem package
一样,是一个经常被使用的package,也是Laravel框架的一个重要依赖之一。AWS SDK for PHP
也是把该package作为一个基础package来使用,以后也想就AWS SDK for PHP
做一些个人分享,对AWS开发感兴趣的可以参看官方文档AWS SDK for PHP,并且AWS提供了官方认证考试:初级开发者证书AWS Certified Developer Associate,高级DevOps工程师证书AWS Certified DevOps Engineer Professional
,感兴趣可以参考官网:AWS Certification。学习Laravel不仅仅需要学习框架的使用和源码,也需要学习这些常用package的使用,这些优秀的package提供了很多代码设计思想和架构概念,这对提高个人设计代码时的能力大有裨益。
本小篇主要学习下Guzzle package
的Stream
概念和使用,如果对Guzzle package
不是很了解可以看下官网Guzzle。
Streams
一次HTTP请求是由起始行、消息头、消息体组成的,消息体(payloads
)可以是很小或者很大,如果使用字符串来存储消息体的话,对于很大的消息体如一个大文件,用字符串存储就会很消耗内存,所以对于大消息体就需要使用Stream来表示。Guzzle使用了\Psr\Http\Message\StreamInterface
来表示该Stream Objects
,该接口也是对PHP Streams的抽象,暴露了一些常用方法:判断stream是否满足要求的方法,isReadable(), isWriable(), isSeekable()
;stream的读写相关操作,read(), write(), close()
;获取元数据方法,getMetadata(), getSize()
;stream操作指针相关方法,rewind(), tell(), eof(), seek()
,等等。
在psr/http-message package中提供了如下接口:\Psr\Http\Message\StreamInterface, \Psr\Http\Message\RequestInterface, \Psr\Http\Message\ServerRequestInterface, \Psr\Http\Message\ResponseInterface, \Psr\Http\Message\MessageInterface, \Psr\Http\Message\UriInterface, \Psr\Http\Message\UploadedFileInterface
。而guzzle/psr7 package提供了这些接口对应的实现:\GuzzleHttp\Psr7\Stream, \GuzzleHttp\Psr7\Request, \GuzzleHttp\Psr7\ServerRequest, \GuzzleHttp\Psr7\Response, \GuzzleHttp\Psr7\Message, \GuzzleHttp\Psr7\Uri, \GuzzleHttp\Psr7\UploadedFile。
本篇主要学习下\GuzzleHttp\Psr7\Stream
相关使用。
Creating Streams
构造一个stream最好方式是使用GuzzleHttp\Psr7\stream_for
,该方法可以接收string, resources from open(), object implements __toString() or Psr\Http\Message\StreamInterface, callables, iterators
,写一个PHPUnit测试看下stream的创建,爆绿灯:
// tests/Guzzle/StreamTest.php namespace App\Tests\Guzzle; class StreamTest extends TestCase { public function testCreatingStringStream() { /** @var \GuzzleHttp\Psr7\Stream $stream */ $stream = \GuzzleHttp\Psr7\stream_for('Laravel is a stream.'); $this->assertEquals('Laravel is a stream.', $stream); $stream = \GuzzleHttp\Psr7\stream_for('Laravel is a stream.'); $this->assertEquals('Laravel', $stream->read(7)); $this->assertEquals(' is a stream.', $stream->getContents()); $this->assertEquals(true, $stream->eof()); $this->assertEquals(20, $stream->tell()); } } // tests/Guzzle/TestCase.php namespace App\Tests\Guzzle; use App\Tests\TestCase as BaseCase; abstract class TestCase extends BaseCase { }
还可以把iterator
作为参数来构造stream,PHPUnit测试爆绿灯:
public function testCreatingIteratorStream() { $generator = function ($num) { for ($i = 0; $i < $num; $i++) { yield 'laravel.'; } }; $stream = \GuzzleHttp\Psr7\stream_for($generator(3)); $this->assertEquals('laravel.laravel.laravel.', $stream->read(24)); }
还可以把一个resource
作为参数来构造stream,PHPUnit测试爆绿灯:
public function testResourceStreamMetadata() { $resource = fopen(storage_path('/logs/laravel.log'), 'r'); $stream = \GuzzleHttp\Psr7\stream_for($resource); $this->assertEquals(storage_path('/logs/laravel.log'), $stream->getMetadata('uri')); $this->assertTrue($stream->isReadable()); $this->assertFalse($stream->isWritable()); $this->assertTrue($stream->isSeekable()); }
Stream Decorators
Guzzle
也提供了一些Stream Decorators
来修饰stream handlers,这些Decorators
主要包括以下几种:
AppendStream
BufferStream
CachingStream
DroppingStream
FnStream
InflateStream
LazyOpenStream
LimitStream
NoSeekStream
PumpStream
这里仅仅以\GuzzleHttp\Psr7\AppendStream
为例说明下Stream Decorator
的使用,其他的Decorator可以参考官网。AppendStream
修饰器顾名思义就是可以读取多个stream并拼接成一个stream,PHPUnit测试爆绿灯:
public function testAppendStream() { $stream1 = \GuzzleHttp\Psr7\stream_for('Laravel'); $stream2 = \GuzzleHttp\Psr7\stream_for(' is '); $stream3 = \GuzzleHttp\Psr7\stream_for('great!!!'); $append_stream = new \GuzzleHttp\Psr7\AppendStream([$stream1, $stream2]); $append_stream->addStream($stream3); $this->assertEquals('Laravel is great!!!', $append_stream); }
总结:学习Guzzle Package的使用是必要的,该package经常作为一个重要依赖被其他package使用,比如AWS SDK for PHP就严重使用该package来做HTTP请求。后续还会分享Guzzle Package相关使用,到时见。