react/filesystem

异步文件系统抽象。

资助包维护!
Open Collective

v0.1.2 2018-10-22 12:10 UTC

This package is auto-updated.

Last update: 2024-08-26 09:32:20 UTC


README

CI status

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()

工厂

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 是所有其他节点接口(如 FileInterfaceDirectoryInterface)的核心。它提供了对所有类型节点都有用的基本方法。

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!')
});

安装

安装此库的推荐方法是 通过 ComposerComposer 初学者?

一旦发布,此项目将遵循 SemVer。目前,这将安装最新开发版本

composer require react/filesystem:^0.2@dev

有关版本升级的详细信息,请参阅 变更日志

此项目旨在在任何平台上运行,因此不需要任何 PHP 扩展,并支持在 PHP 7.4 至当前 PHP 8+ 上运行。强烈建议为此项目使用支持的最新 PHP 版本。

建议安装任何事件循环扩展,但这完全是可选的。有关更多详细信息,请参阅 事件循环实现

测试

要运行测试套件,您首先需要克隆此仓库,然后通过 Composer 安装所有依赖项 (通过 Composer)

composer install

要运行测试套件,请转到项目根目录并运行

vendor/bin/phpunit

许可证

MIT 许可,请参阅 许可文件