react / filesystem
异步文件系统抽象。
Requires
- php: >=5.4.0
- evenement/evenement: ^3.0 || ^2.0
- react/event-loop: ^1.0 || ^0.5 || ^0.4
- react/promise: ~2.2
- react/promise-stream: ^1.1
- react/stream: ^1.0 || ^0.7 || ^0.6 || ^0.5 || ^0.4
- wyrihaximus/react-child-process-pool: ^1.3
Requires (Dev)
- clue/block-react: ^1.1
- phpunit/phpunit: ^6.0 || ^5.0 || ^4.8
Suggests
- ext-eio: ^1.2
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();
此方法始终返回一个实现适配器接口
的实例,实际的文件系统实现是一个实现细节。
此方法可以在任何时候调用。然而,某些调度机制会被使用,这会使事件循环因为每个新的文件系统适配器实例而变得更加繁忙。为了避免这种情况,建议您创建一次,并在需要的地方注入。
文件系统实现
除了文件系统接口
之外,还提供了一系列文件系统实现。
所有文件系统都支持以下功能
- 声明节点
- 列出目录内容
- 从文件中读取/写入
对于大多数此包的消费者,底层文件系统实现是一个实现细节。您应该使用Factory
来自动创建一个新实例。
工厂将确定最适合您环境的文件系统。任何基于扩展的文件系统都优先于性能较低的文件系统。当检测不到任何扩展时,将回退到使用阻塞系统调用的内部回退文件系统。因此,强烈建议安装其中一个扩展,以解锁更高效的文件系统操作。
高级!如果您需要特定的文件系统实现,可以手动实例化以下类之一。请注意,您可能必须首先安装相应的事件循环实现的必需PHP扩展,否则它们在创建时会抛出BadMethodCallException
。
Eio
基于ext-eio
的文件系统。
这个文件系统使用了eio
PECL 扩展,该扩展提供了一个到 libeio
库的接口。
该文件系统已知与 PHP 7+ 兼容。
Uv
一个基于 ext-uv
的文件系统。
该文件系统使用了uv
PECL 扩展,该扩展提供了一个到 libuv
库的接口。
该文件系统已知与 PHP 7+ 兼容。
适配器接口
detect()
detect(string $path): PromiseInterface<NodeInterface>
是获取表示文件系统上节点的对象的推荐方式。
调用此方法时,它将尝试检测您提供的路径是哪种类型的节点,并返回一个实现 NodeInterface
的对象。如果给定路径不存在,将返回一个 NotExistInterface
对象,您可以使用它来创建文件或目录。
directory()
directory(string $path): DirectoryInterface
在指定路径创建表示目录的对象。
请注意,与 detect
方法不同,directory
方法不能保证您传入的路径实际上是文件系统上的目录,可能会导致意外行为。
file()
file(string $path): DirectoryInterface
在指定路径创建表示文件的对象。
请注意,与 detect
方法不同,file
方法不能保证您传入的路径实际上是文件系统上的文件,可能会导致意外行为。
节点接口
NodeInterface
是所有其他节点接口(如 FileInterface
或 DirectoryInterface
)的核心。它提供了对所有类型节点都有用的基本方法。
path()
path(): string
方法返回节点位置的路径部分。因此,如果完整路径是 /path/to/file.ext
,则此方法返回 /path/to/
。
name()
name(): string
方法返回节点位置的名称部分。因此,如果完整路径是 /path/to/file.ext
,则此方法返回 file.ext
。
stat()
stat(): PromiseInterface<?Stat>
方法对节点进行统计,并提供有关其大小、完整路径、创建/更新时间等信息。
目录接口
ls
ls(): PromiseInterface<array<NodeInterface>>
方法列出给定目录的所有内容,并将返回包含节点的数组。它将尽力检测节点类型,否则回退到 FilesystemInterface::detect(string $path): PromiseInterface<NodeInterface>
。
文件接口
此接口上的 *Contents
方法旨在尽可能与 PHP 的 file_(get|put)_contents
函数的行为相同。结果是一个非常熟悉的 API,用于从文件中读取/流式传输,或将内容写入/附加到文件。
getContents
对于从文件中读取,getContents(int $offset = 0 , ?int $maxlen = null): PromiseInterface<string>
提供了两个参数,用于控制从文件中读取多少数据。如果没有参数,它将读取所有内容
$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<int>
的特例。默认情况下,当传递内容时,如果文件存在,它将截断文件,或者创建一个新的文件并将其填充给定内容。
$file->putContents('ReactPHP');
支持向文件追加,通过使用 \FILE_APPEND
常量,如果文件存在,则将其附加到文件。
$file->putContents(' is awesome!', \FILE_APPEND);
不存在接口
两种创建方法都会检查父目录是否存在,如果不存在,则创建它。这使创建过程是递归的。
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 初学者?
一旦发布,此项目将遵循 SemVer。目前,这将安装最新开发版本
composer require react/filesystem:^0.2@dev
有关版本升级的详细信息,请参阅 变更日志。
此项目旨在在任何平台上运行,因此不需要任何 PHP 扩展,并支持在 PHP 7.4 至当前 PHP 8+ 上运行。强烈建议为此项目使用支持的最新 PHP 版本。
建议安装任何事件循环扩展,但这完全是可选的。有关更多详细信息,请参阅 事件循环实现。
测试
要运行测试套件,您首先需要克隆此仓库,然后通过 Composer 安装所有依赖项 (通过 Composer)
composer install
要运行测试套件,请转到项目根目录并运行
vendor/bin/phpunit
许可证
MIT 许可,请参阅 许可文件。