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 packageStream概念和使用,如果对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相关使用,到时见。

RightCapital招聘Laravel DevOps

相关推荐