trunglv / stream
Hoa\Stream 库。
Requires
- php: >=8.0
- hoa/event: dev-master
- hoa/exception: dev-master
- trunglv/consistency: dev-master
- trunglv/protocol: dev-master
Requires (Dev)
- hoa/test: dev-master
This package is auto-updated.
Last update: 2024-09-13 03:54:58 UTC
README
Hoa 是一套 模块化、可扩展 和 结构化 的 PHP 库。
此外,Hoa 致力于成为工业界和研究界之间的桥梁。
Hoa\Stream
此库是 PHP 流的高级抽象。它包括
- 流操作:打开、关闭、自动关闭、超时、阻塞模式、缓冲区大小、元数据等
- 流通知:根据流包装器,支持的监听器包括以下内容:
authrequire
、authresult
、complete
、connect
、failure
、mimetype
、progress
、redirect
、resolve
和size
- 上下文:允许向流包装器传递选项和参数,例如 HTTP 头
- 过滤器:一个位于流源和目标之间的函数,例如用于加密/解密数据或在飞行中执行更高级技巧(如仪表化)非常有用
- 包装器:声明用户定义的协议,这些协议将自然地由 PHP 标准库处理(如
fopen
、stream_get_contents
等) - 接口:每个接口代表流可以提供的一种能力
此库是其他几个库的基础,例如 Hoa\File
或 Hoa\Socket
(以及 Hoa\Websocket
)。
了解更多.
安装
使用 Composer,要将此库包含在依赖项中,您需要要求 hoa/stream
$ composer require hoa/stream '~1.0'
有关更多安装程序,请阅读源代码页面。
测试
在运行测试套件之前,必须安装开发依赖项
$ composer install
然后,要运行所有测试套件
$ vendor/bin/hoa test:run
有关更多信息,请阅读贡献者指南。
快速使用
作为一个快速概述,我们建议发现 Hoa\Stream
在接口方面的提供,即流能力。这是此库中最重要的部分。然后,如何定义一个流,接着是使用流上下文。事件、监听器和通知将在下一节中详细说明。最后,包装器和过滤器将在最后几节中详细说明。
接口,即流能力
此库定义了几个接口,表示重要的流能力。在设计一个函数或与流一起工作的库时非常有用。它确保流是类型化的并提供某些能力。接口在 Hoa\Stream\IStream
命名空间中声明
In
,从流中读取,提供read
、readInteger
、readLine
、readAll
、eof
等Out
,向流写入,提供write
、writeArray
、writeLine
、truncate
等Bufferable
,对于具有至少一个内部缓冲区的流,提供newBuffer
、flush
、getBufferLevel
等Touchable
,对于“可触摸”的流,提供touch
、copy
、move
、delete
、changeGroup
等Lockable
,用于锁定流,提供lock
以及代表不同类型锁的几个常量,如LOCK_SHARED
、LOCK_EXCLUSIVE
、LOCK_NO_BLOCK
等。Pathable
,针对基于路径的流,提供getBasename
和getDirname
。Pointable
,用于移动流内部指针(如果有),提供rewind
、seek
和tell
。Statable
,用于获取有关流的统计信息,提供getSize
、getStatistics
、getATime
、getCTime
、isReadable
等。Structural
,针对结构化流(即像树一样的流),提供selectRoot
、selectAnyElements
、selectElements
、selectAdjacentSiblingElement
、querySelector
等。
因此,如果只需要从流中读取,则可以使用Hoa\Stream\IStream\In
来表示该流。它还允许实现者选择其流将提供或不会提供哪些功能。
最高接口是Stream
,定义了getStream
方法,就这么多。这是最未定义的流。所有功能都必须扩展此接口。
定义一个具体的流
主要的Hoa\Stream\Stream
类是抽象的。留给用户两个方法实现:_open
和_close
,分别用于打开特定的流和关闭该特定的流,例如
class BasicFile extends Hoa\Stream\Stream { protected function &_open($streamName, Hoa\Stream\Context $context = null) { if (null === $context) { $out = fopen($streamName, 'rb'); } else { $out = fopen($streamName, 'rb', false, $context->getContext()); } return $out; } protected function _close() { return fclose($this->getStream()); } }
然后,最常用的用法将是
$file = new BasicFile('/path/to/file');
这就是全部。这个流还没有任何功能。让我们实现In
功能
class BasicFile extends Hoa\Stream\Stream implements Hoa\Stream\IStream\In { // … public function read($length) { return fread($this->getStream(), max(1, $length)); } // … }
其他方法留给读者作为练习。因此,我们现在能够
$chunk = $file->read(42);
Stream
功能已经由Hoa\Stream\Stream
类实现。
上下文流
上下文由Hoa\Stream\Context
类表示。它表示流的选项和参数集。请参阅http://的选项和参数示例,作为可能的一些示例。多亏了上下文,可以添加HTTP头信息,或指定代理、最大重定向次数等。所有这些信息都是流的选项/参数。
要使用它们,首先让我们定义上下文
$contextId = 'my_http_context'; $context = Hoa\Stream\Context::getInstance($contextId); $context->setOptions([ // … ]);
因此,我们可以要求一个流根据所选的上下文ID使用此上下文,如下所示
$basicFile = new BasicFile('/path/to/file', $contextId);
对于流实现者,Hoa\Stream\Context
类上的getOptions
和getParameters
方法将很有用,分别用于检索选项和参数,并根据它们执行操作。
“选项”和“参数”的概念由PHP本身定义。
事件、监听器和通知
流有一些事件和多个监听器。到目前为止,监听器大多代表“流通知”。
已注册了2个事件:hoa://Event/Stream/<streamName>
和hoa://Event/Stream/<streamName>:close-before
。例如,要在一个文件流关闭前执行函数,可以这样写
Hoa\Event\Event::getEvent('hoa://Event/Stream//path/to/file:close-before')->attach( function (Hoa\Event\Bucket $bucket) { // do something! } );
记住,流不一定是文件。它可以是一个套接字、WebSocket、字符串缓冲区、您定义的任何流……因此,这个事件可以用于各种场景,如记录信息、关闭相关资源、触发另一个事件……没有规则。观察到的流仍然是打开的,理论上仍然可以使用。
在调用Hoa\Stream\Stream::close
方法时触发此事件。
现在让我们转到监听器。要注册一个监听器,我们必须创建一个未打开的流实例。这个动作被称为“延迟打开”。我们可以通过默认Hoa\Stream\Stream
构造函数的第三个参数控制打开时间;true
以延迟打开,如下所示
$file = new BasicFile('/path/to/file', null, true); // do something $file->open();
将null
作为第二个参数意味着:没有上下文。请注意,我们必须手动调用open
方法来打开流。在流实例化和流打开之间,我们可以附加新的监听器。
根据流实现的不同,将触发不同的监听器。在Hoa中,术语“监听器”被用于各个地方,但在PHP的流上下文中,它们被称为通知。让我们以HTTP流为例。
$basic = new BasicFile( 'https://hoa-project.net/', // stream name null, // context ID true // defere opening ); $basic->on( 'connect', function (Hoa\Event\Bucket $bucket) { echo 'Connected', "\n"; } ); $basic->on( 'redirect', function (Hoa\Event\Bucket $bucket) { echo 'Redirection to ', $bucket->getData()['message'], "\n"; } ); $basic->on( 'mimetype', function (Hoa\Event\Bucket $bucket) { echo 'MIME-Type is ', $bucket->getData()['message'], "\n"; } ); $basic->on( 'size', function (Hoa\Event\Bucket $bucket) { echo 'Size is ', $bucket->getData()['max'], "\n"; } ); $basic->on( 'progress', function (Hoa\Event\Bucket $bucket) { echo 'Progressed, ', $bucket->getData()['transferred'], ' bytes downloaded', "\n"; } ); // Then open. $basic->open();
你可能看到类似的内容
Connected
MIME-Type is text/html; charset=UTF-8
Redirection to /En/
Connected
MIME-Type is text/html; charset=UTF-8
Progressed, … bytes downloaded
Progressed, … bytes downloaded
监听器的完整列表如下
authrequire
,当需要认证时,authresult
,当认证结果已知时,complete
,当流完成时(含义可能很多),connect
,当流连接时(含义可能很多),failure
,当发生意外情况时,mimetype
,当流的MIME类型已知时,progress
,当有显著进展时,redirect
,当流被重定向到另一个流时,resolve
,当流解析完成时(含义可能很多),size
,当流的尺寸已知时。
所有监听器桶数据是一个包含以下对的数组
code
,一个STREAM_NOTIFY_*
常量之一,基本上是监听器名称(见文档),severity
,一个STREAM_NOTIFY_SEVERITY_*
常量STREAM_NOTIFY_SEVERITY_INFO
,正常,非错误相关的通知,STREAM_NOTIFY_SEVERITY_WARN
,非关键错误条件,处理可以继续,STREAM_NOTIFY_SEVERITY_ERR
,发生了关键错误,处理无法继续。
message
,包含大部分有用信息的字符串,transferred
,已传输的字节数,max
,要传输的总字节数。
流的实现者可以添加更多的监听器。请参阅Hoa\Event
库。并非所有监听器都会在所有类型的流中被触发。
包装器
流包装器允许声明方案,如hoa://
或fortune://
。你可以想象添加你喜欢的在线存储,如cloud://
。任何流包装器都可以与原生标准PHP函数一起使用,如fopen
、file_get_contents
、mkdir
、touch
等。对用户来说是透明的。
Hoa\Stream\Wrapper\Wrapper
类包含所有用于register
、unregister
和restore
包装器的操作方法。isRegistered
和getRegistered
方法也很有帮助。包装器由一个类表示
Hoa\Stream\Wrapper\Wrapper::register('tmp', Tmp::class);
包装器必须实现Hoa\Stream\Wrapper\IWrapper\IWrapper
接口。它是同一命名空间中两个其他接口的组合:Stream
和File
。
Stream
接口要求实现与流相关的多个方法,例如
stream_open
,stream_close
,stream_cast
,stream_eof
,stream_flush
,stream_lock
,stream_metadata
,stream_read
,stream_write
,stream_seek
,stream_tell
,stream_stat
,- 等等。
API提供了所有必需的信息。
File
接口要求实现与其他与流作为文件操作相关的其他方法,例如
mkdir
,dir_opendir
,dir_closedir
,dir_readdir
,rename
,unlink
,- 等等。
实现示例是Hoa\Protocol
库中的hoa://
方案。它不依赖于这个库以避免依赖关系,但代码可能很有帮助。
过滤器
流就像一个管道,有输入和输出。这是可能的将这个管道切成两段,并插入一小部分:一个过滤器。有三种类型的过滤器,由Hoa\Stream\Filter\Filter
类上的常量来识别
Filter::READ
,当过滤器适用于读取操作时,- 当过滤器应用于写操作时,使用
Filter::WRITE
, - 当两者都应用时,使用
Filter::READ_AND_WRITE
。
该类允许 register
或 remove
过滤器。一个过滤器是扩展了 Hoa\Stream\Filter\Basic
过滤器的类,以及一个相关联的名称。这并非强制要求,但非常鼓励。
一旦注册了过滤器,我们就可以通过使用其名称,通过 append
或 prepend
方法将其应用于流。你可能已经猜到了,可以在流上应用多个过滤器,按特定顺序,如“解密”,“解压缩”,“转换为...”。在这种情况下,顺序很重要。
最后,我们像往常一样使用流。流不一定是 Hoa\Stream
的实例,它可以是任何 PHP 流资源。传递一个 Hoa\Stream
实例将显然展开为其底层的 PHP 流资源。
让我们实现一个过滤器,它将流的内容转换为大写。我们首先定义我们的过滤器
class ToUpper extends Hoa\Stream\Filter\Basic { public function filter($in, $out, &$consumed, $closing) { $iBucket = new Hoa\Stream\Bucket($in); $oBucket = new Hoa\Stream\Bucket($out); while (false === $iBucket->eob()) { $consumed += $iBucket->getLength(); $iBucket->setData(strtoupper($iBucket->getData())); $oBucket->append($iBucket); } unset($iBucket); unset($oBucket); return parent::PASS_ON; } }
太好了。现在让我们将我们的过滤器注册到特定的名称下
$filterName = 'toupper'; Hoa\Stream\Filter::register($filterName, ToUpper::class);
然后,我们必须在特定的流上应用这个过滤器,所以让我们打开一个流,并附加过滤器
$file = new Hoa\File\Read(__FILE__); Hoa\Stream\Filter::append($file, $filterName, Hoa\Stream\Filter::READ);
这个过滤器只应用于读取操作。所以当我们读取我们的流时,我们会看到它的效果,让我们来做这件事
echo $file->readAll();
你会看到所有内容都是 ASCII 大写。
过滤器是一个低级流 API。它与所有类型的流集成。这是一个非常强大的工具。我们提到了一些用法,如解密、转换、解压缩等。实际上,PHP 附带了一些标准过滤器,如:string.toupper
、string.tolower
、dechunk
、zlib.*
、bzip2.*
、convert.iconv.*
等。使用 Hoa\Stream\Filter\Filter::getRegistered
方法将提供所有已注册过滤器的列表。
Hoa\Stream\Filter\LateComputed
类是一个特殊过滤器。它在流达到其末尾时调用其公共 compute
方法。因此,通过扩展此过滤器,你可以重写 compute
方法并操作 _buffer
属性。该缓冲区包含流的所有内容。这真的是一个缓冲区。为什么会有用?例如,如果你正在读取一个 PHP 文件,你可以通过解析器(例如)即时转换源代码并重写文件的一部分。这项技术特别适用于对代码进行仪器化(添加一些探测器)。
也可以使用包装器自动应用过滤器!例如,instrument://
包装器可以使用 stream_open
方法(来自 Hoa\Stream\Wrapper\IWrapper\Stream
接口)将过滤器附加到正在打开的流上。
可能性是无穷无尽的。
其他操作
还有更多内容要介绍。 Hoa\Stream
支持复合流(使用 Hoa\Stream\Composite
抽象类),即嵌入其他流的流,例如 Hoa\Xml
库。XML 流从另一个内部流(文件、套接字或任何其他内容)读取和写入。 Hoa\Stringbuffer
库 允许使用流 API 操作字符串,因此流内容将写入磁盘。与 Hoa\File
不同,流的功能可能不同。
文档
Hoa\Stream
的黑客手册 包含有关如何使用此库及其工作方式的详细信息。
要本地生成文档,请执行以下命令
$ composer require --dev hoa/devtools $ vendor/bin/hoa devtools:documentation --open
更多文档可以在项目的网站上找到: hoa-project.net。
获取帮助
主要有两种获取帮助的方法
- 在
#hoaproject
IRC 频道中, - 在 users.hoa-project.net 的论坛上。
贡献
您想贡献吗?谢谢!一份详细的贡献指南解释了您需要了解的所有内容。
许可证
Hoa采用新BSD许可证(BSD-3-Clause)。请参阅LICENSE
获取详细信息。
相关项目
以下项目正在使用这个库
- Marvirc,一个简单、极度模块化和极快的IRC机器人,
- WellCommerce,基于Symfony 3全栈框架的现代电子商务引擎,
- 当然还有许多Hoa的库。