xdimedrolx / hoa-stream
Hiqdev Hoa\Stream 库。
Requires
- php: >=7.4
- hoa/consistency: ~1.0
- hoa/event: ~1.0
- hoa/exception: ~1.0
- xdimedrolx/hoa-protocol: ~1.0
Requires (Dev)
- hoa/test: ~2.0
Replaces
- hoa/stream: ~1.17
This package is not auto-updated.
Last update: 2024-09-21 10:07:17 UTC
README
Hoa 项目已被归档,不提供升级或补丁,也不会接受合并请求。
HOA 包包含一些针对 PHP 8.0 和 PHP 8.1 已弃用的代码,但我们需要这些包在现代 PHP 版本上运行。
从哪里变更了?
更改主要影响了方法声明中的返回数据类型提示,以及未初始化属性的访问。
如何使用
我们目前已分叉了以下包,主要是为了使 hoa/stream 与 PHP 8.1 兼容
您只需简单地从 composer.json 中的 hoa 包替换为相应的分叉包:无需更改代码库中的任何内容。如果您使用某人需要 hoa 的包,只需将分叉添加到您的项目根 composer.json 中:我们已经将分叉标记为替代品,所以 composer 将安装它们而不是原始包。
版本
我们从最新的 hoa 包版本分叉,并从 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。例如,要在 /path/to/file 流关闭之前执行一个函数,可以这样写
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当两者都应用时。
此类允许注册或删除过滤器。过滤器采用扩展自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的hack书包含了有关如何使用此库及其工作原理的详细信息。
要本地生成文档,请执行以下命令
$ composer require --dev hoa/devtools $ vendor/bin/hoa devtools:documentation --open
更多文档可以在项目的网站上找到:hoa-project.net。
获取帮助
主要有两种方式可以获得帮助
- 在
#hoaprojectIRC频道中 - 在users.hoa-project.net的论坛上。
贡献
您想贡献吗?谢谢!详细的贡献指南解释了您需要了解的所有内容。
许可证
Hoa采用新BSD许可证(BSD-3-Clause)。请参阅LICENSE以获取详细信息。
相关项目
以下项目正在使用此库
- Marvirc,一个简单、模块化且速度极快的IRC机器人
- WellCommerce,基于Symfony 3全栈框架的现代电子商务引擎
- 当然,还有许多Hoa库。