wpjscc / filesystem
Requires
- php: >=7.4.0
- react/event-loop: ^1.2
- react/promise: ^3 || ^2.8
- react/promise-stream: ^1.2
- react/stream: ^1.2
Requires (Dev)
- phpunit/phpunit: ^9.5
- react/async: ^4 || ^3
Suggests
- ext-eio: * for great I/O performance
- ext-uv: * for better I/O performance
README
ReactPHP 的文件系统组件,支持非阻塞文件系统操作。
开发版本:此分支包含即将发布的 0.2 版本的代码,这将为本包的未来发展指明方向。
有关详细信息,请参阅安装说明。
目录
快速入门示例
以下是一个列出当前目录中所有内容的程序。
use React\Filesystem\Factory; use React\Filesystem\Node\DirectoryInterface; use React\Filesystem\Node\NodeInterface; Factory::create()->detect(__DIR__)->then(function (DirectoryInterface $directory) { return $directory->ls(); })->then(static function ($nodes) { foreach ($nodes as $node) { assert($node instanceof NodeInterface); echo $node->name(), ': ', get_class($node), PHP_EOL; } echo '----------------------------', PHP_EOL, 'Done listing directory', PHP_EOL; }, function (Throwable $throwable) { echo $throwable; });
有关示例,请参阅示例。
使用
工厂
Factory
类存在是为了方便选择最佳可用的 文件系统实现。
create()
可以使用 create(): AdapterInterface
方法创建一个新的文件系统实例
$filesystem = \React\Filesystem\Factory::create();
此方法始终返回一个实现 adapterinterface
的实例,实际的 文件系统实现 是一个实现细节。
此方法可以随时调用。但是,某些调度机制会被使用,这将使事件循环因为每个新的文件系统适配器实例而变得繁忙。为了避免这种情况,建议您只创建一次,并在需要的地方注入它。
文件系统实现
除了 FilesystemInterface
之外,还提供了一系列文件系统实现。
所有文件系统都支持以下功能
- 声明节点
- 列出目录内容
- 从文件中读取/写入
对于此包的大多数消费者来说,底层文件系统实现是一个实现细节。您应该使用 Factory
来自动创建新实例。
工厂将确定您环境中最有效的文件系统。任何基于扩展的文件系统都优先于性能较差的文件系统。当未检测到任何扩展时,它将回退到使用阻塞系统调用的内部回退文件系统。因此,强烈建议安装一个扩展,以解锁更高效的文件系统操作。
高级!如果您明确需要某个文件系统实现,可以手动实例化以下类之一。请注意,您可能必须首先安装相应事件循环实现的必需 PHP 扩展,否则它们在创建时会抛出 BadMethodCallException
。
Eio
基于 ext-eio
的文件系统。
此文件系统使用 eio
PECL 扩展,它提供了对 libeio
库的接口。
已知此文件系统与 PHP 7+ 兼容。
Uv
基于 ext-uv
的文件系统。
该文件系统使用了uv
PECL扩展,该扩展提供了一个访问libuv
库的接口。
已知此文件系统与 PHP 7+ 兼容。
AdapterInterface
detect()
推荐使用detect(string $path): PromiseInterface
方法来获取表示文件系统上节点的对象。
调用此方法时,它会尝试检测提供的路径是哪种类型的节点,并返回一个实现NodeInterface
的对象。如果给定路径不存在,将返回一个NotExistInterface
对象,您可以使用该对象创建文件或目录。
directory()
directory(string $path): DirectoryInterface
方法创建一个表示指定路径上的目录的对象。
请注意,与detect
方法不同,directory
方法不能保证您传递的路径在文件系统中实际是一个目录,可能会导致意外的行为。
file()
file(string $path): DirectoryInterface
方法创建一个表示指定路径上的文件的对象。
请注意,与detect
方法不同,file
方法不能保证您传递的路径在文件系统中实际是一个文件,可能会导致意外的行为。
NodeInterface
NodeInterface
是所有其他节点接口(如FileInterface
或DirectoryInterface
)的核心。它提供了对所有类型节点都很有用的基本方法。
path()
path(): string
方法返回节点位置的路径部分。因此,如果完整路径是/path/to/file.ext
,则此方法返回/path/to/
。
name()
name(): string
方法返回节点位置的名称部分。因此,如果完整路径是/path/to/file.ext
,则此方法返回file.ext
。
stat()
stat(): PromiseInterface
方法对节点进行统计并提供有关其大小、完整路径、创建/更新时间等信息。
DirectoryInterface
ls
ls(): PromiseInterface
方法列出给定目录的所有内容,并返回一个包含节点数组的数组。它将尽可能检测节点的类型,否则将回退到FilesystemInterface::detect(string $path): PromiseInterface
。
FileInterface
该接口上的*Contents
方法旨在尽可能与PHP的file_(get|put)_contents
函数的行为一致。结果是一个非常熟悉的API,可以用于从文件中读取/流式传输,或将内容写入/追加到文件。
getContents
对于从文件读取,getContents(int $offset = 0, ?int $maxlen = null): PromiseInterface
提供了两个参数,用于控制从文件中读取的数据量。如果没有参数,则读取全部内容。
$file->getContents();
偏移量和最大长度允许您“选择”要读取的文件的一部分。下面的示例将跳过前2048
个字节,然后从文件中读取最多1024
个字节。然而,如果文件在2048
偏移量之后只包含512
个字节,它将只返回这些512
个字节。
$file->getContents(2048, 1024);
可以使用定时器作为触发器来检查更新来跟踪文件。
$offset = 0; Loop::addPeriodicTimer(1, function (TimerInterface $timer) use ($file, &$offset, $loop): void { $file->getContents($offset)->then(function (string $contents) use (&$offset, $timer, $loop): void { echo $contents; // Echo's the content for example purposes $offset += strlen($contents); }); });
putContents
向文件写入是putContents(string $contents, int $flags = 0): PromiseInterface
的特例。默认情况下,当传递内容时,如果文件存在,则截断文件;如果不存在,则创建一个新文件并将其填充给定的内容。
$file->putContents('ReactPHP');
支持向文件追加,使用\FILE_APPEND
常量,如果文件存在,则将其追加。
$file->putContents(' is awesome!', \FILE_APPEND);
NotExistInterface
两种创建方法都会检查父目录是否存在,如果不存在,则创建它。这实际上使创建过程递归。
createDirectory
以下示例将创建lets/make/a/nested/directory
作为递归目录结构。
$filesystem->directory( __DIR__ . 'lets' . DIRECTORY_SEPARATOR . 'make' . DIRECTORY_SEPARATOR . 'a' . DIRECTORY_SEPARATOR . 'nested' . DIRECTORY_SEPARATOR . 'directory' )->createDirectory();
createFile
以下操作将在lets/make/a/nested/directory
目录中创建with-a-file.txt
文件,并将This is amazing!
写入该文件。
use React\Filesystem\Node\FileInterface; $filesystem->file( __DIR__ . 'lets' . DIRECTORY_SEPARATOR . 'make' . DIRECTORY_SEPARATOR . 'a' . DIRECTORY_SEPARATOR . 'nested' . DIRECTORY_SEPARATOR . 'directory' . DIRECTORY_SEPARATOR . 'with-a-file.txt' )->createFile()->then(function (FileInterface $file) { return $file->putContents('This is amazing!') });
安装
推荐使用Composer安装此库。如果您是Composer的新用户,请参阅Composer入门指南。
一旦发布,该项目将遵循SemVer。目前,这将安装最新的开发版本。
composer require react/filesystem:^0.2@dev
有关版本升级的详细信息,请参阅变更日志。
该项目旨在在任何平台上运行,因此不需要任何PHP扩展,并支持从PHP 7.4到当前PHP 8+的运行。强烈建议使用该项目支持的最新PHP版本。
建议安装事件循环扩展,但这完全是可选的。有关更多详细信息,请参阅事件循环实现。
测试
要运行测试套件,首先需要克隆此仓库,然后通过Composer安装所有依赖项。
composer install
要运行测试套件,请转到项目根目录并运行
vendor/bin/phpunit
许可证
MIT许可,请参阅LICENSE文件。