{"id":18941218,"url":"https://github.com/reactphp/filesystem","last_synced_at":"2025-04-04T14:05:20.309Z","repository":{"id":23369706,"uuid":"26731001","full_name":"reactphp/filesystem","owner":"reactphp","description":"Evented filesystem access.","archived":false,"fork":false,"pushed_at":"2024-03-26T08:38:46.000Z","size":608,"stargazers_count":135,"open_issues_count":26,"forks_count":40,"subscribers_count":18,"default_branch":"0.2.x","last_synced_at":"2024-04-13T16:34:01.363Z","etag":null,"topics":["eio","filesystem","php","reactphp"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/reactphp.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null},"funding":{"github":["reactphp","clue","WyriHaximus"],"open_collective":"reactphp"}},"created_at":"2014-11-16T22:49:21.000Z","updated_at":"2024-04-15T00:41:20.472Z","dependencies_parsed_at":"2024-04-15T00:40:56.756Z","dependency_job_id":"dccea2b2-ca7c-4351-b870-f9302be737b8","html_url":"https://github.com/reactphp/filesystem","commit_stats":{"total_commits":587,"total_committers":12,"mean_commits":"48.916666666666664","dds":0.04599659284497448,"last_synced_commit":"385933fdf47ad2db195c859523a8d854792dbad2"},"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reactphp%2Ffilesystem","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reactphp%2Ffilesystem/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reactphp%2Ffilesystem/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reactphp%2Ffilesystem/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/reactphp","download_url":"https://codeload.github.com/reactphp/filesystem/tar.gz/refs/heads/0.2.x","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245526458,"owners_count":20629835,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["eio","filesystem","php","reactphp"],"created_at":"2024-11-08T12:26:45.274Z","updated_at":"2025-03-28T13:05:13.593Z","avatar_url":"https://github.com/reactphp.png","language":"PHP","readme":"# Filesystem Component\n\n[![CI status](https://github.com/reactphp/filesystem/workflows/CI/badge.svg)](https://github.com/reactphp/filesystem/actions)\n\n[ReactPHP](https://reactphp.org/)'s filesystem component that enables non-blocking filesystem operations.\n\n\u003e **Development version:** This branch contains the code for the upcoming 0.2\n\u003e release which will be the way forward for this package.\n\u003e\n\u003e See [installation instructions](#install) for more details.\n\n**Table of Contents**\n\n* [Quickstart example](#quickstart-example)\n* [Usage](#usage)\n  * [Factory](#factory)\n    * [create()](#create)\n  * [Filesystem implementations](#filesystem-implementations)\n    * [Eio](#eio)\n    * [Uv](#uv)\n  * [AdapterInterface](#adapterinterface)\n    * [detect()](#detect)\n    * [directory()](#directory)\n    * [file()](#file)\n  * [NodeInterface](#nodeinterface)\n    * [path()](#path)\n    * [name()](#name)\n    * [stat()](#stat)\n  * [DirectoryInterface](#directoryinterface)\n    * [ls](#ls)\n  * [FileInterface](#fileinterface)\n    * [getContents()](#getcontents)\n    * [putContents()](#putcontents)\n  * [NotExistInterface](#notexistinterface)\n    * [createDirectory()](#createdirectory)\n    * [createFile()](#createfile)\n* [Install](#install)\n* [Tests](#tests)\n* [License](#license)\n\n## Quickstart example\n\nHere is a program that lists everything in the current directory.\n\n```php\nuse React\\Filesystem\\Factory;\nuse React\\Filesystem\\Node\\DirectoryInterface;\nuse React\\Filesystem\\Node\\NodeInterface;\n\nFactory::create()-\u003edetect(__DIR__)-\u003ethen(function (DirectoryInterface $directory) {\n    return $directory-\u003els();\n})-\u003ethen(static function ($nodes) {\n    foreach ($nodes as $node) {\n        assert($node instanceof NodeInterface);\n        echo $node-\u003ename(), ': ', get_class($node), PHP_EOL;\n    }\n    echo '----------------------------', PHP_EOL, 'Done listing directory', PHP_EOL;\n}, function (Throwable $throwable) {\n    echo $throwable;\n});\n```\n\nSee also the [examples](examples).\n\n## Usage\n\nSee [`Factory::create()`](#create).\n\n### Factory\n\nThe `Factory` class exists as a convenient way to pick the best available\n[filesystem implementation](#filesystem-implementations).\n\n#### create()\n\nThe `create(): AdapterInterface` method can be used to create a new filesystem instance:\n\n```php\n$filesystem = \\React\\Filesystem\\Factory::create();\n```\n\nThis method always returns an instance implementing [`adapterinterface`](#adapterinterface),\nthe actual [Filesystem implementations](#filesystem-implementations) is an implementation detail.\n\nThis method can be called at any time. However, certain scheduling mechanisms are used that will make the event loop \nbusier with every new instance of a filesystem adapter. To prevent that it is preferred you create it once and inject \nit where required.\n\n### Filesystem implementations\n\nIn addition to the [`FilesystemInterface`](#filesysteminterface), there are a number of\nfilesystem implementations provided.\n\nAll the filesystems support these features:\n\n* Stating a node\n* Listing directory contents\n* Reading/write from/to files\n\nFor most consumers of this package, the underlying filesystem implementation is\nan implementation detail.\nYou should use the [`Factory`](#factory) to automatically create a new instance.\n\nThe factory will determine the most performant filesystem for your environment. Any extension based filesystem are \npreferred before falling back to less performant filesystems. When no extensions are detected it will fall back to an \ninternal fallback filesystem that uses blocking system calls. As such it is highly recommended to install one of the \nextensions that unlocks more performant filesystem operations.\n\nAdvanced! If you explicitly need a certain filesystem implementation, you can\nmanually instantiate one of the following classes.\nNote that you may have to install the required PHP extensions for the respective\nevent loop implementation first or they will throw a `BadMethodCallException` on creation.\n\n#### Eio\n\nAn `ext-eio` based filesystem.\n\nThis filesystem uses the [`eio` PECL extension](https://pecl.php.net/package/eio), that\nprovides an interface to `libeio` library.\n\nThis filesystem is known to work with PHP 7+.\n\n#### Uv\n\nAn `ext-uv` based filesystem.\n\nThis filesystem uses the [`uv` PECL extension](https://pecl.php.net/package/uv), that\nprovides an interface to `libuv` library.\n\nThis filesystem is known to work with PHP 7+.\n\n### AdapterInterface\n\n#### detect()\n\nThe `detect(string $path): PromiseInterface\u003cNodeInterface\u003e` is the preferred way to get an object representing a node on the filesystem. \n\nWhen calling this method it will attempt to detect what kind of node the path is you've given it, and return an object \nimplementing [`NodeInterface`](#nodeinterface). If nothing exists at the given path, a [`NotExistInterface`](#notexistinterface) object will be \nreturned which you can use to create a file or directory.\n\n#### directory()\n\nThe `directory(string $path): DirectoryInterface` creates an object representing a directory at the specified path.\n\nKeep in mind that unlike the `detect` method the `directory` method cannot guarantee the path you pass is actually a \ndirectory on the filesystem and may result in unexpected behavior.\n\n#### file()\n\nThe `file(string $path): DirectoryInterface` creates an object representing a file at the specified path.\n\nKeep in mind that unlike the `detect` method the `file` method cannot guarantee the path you pass is actually a\nfile on the filesystem and may result in unexpected behavior.\n\n### NodeInterface\n\nThe `NodeInterface` is at the core of all other node interfaces such as `FileInterface` or `DirectoryInterface`. It \nprovides basic methods that are useful for all types of nodes.\n\n#### path()\n\nThe `path(): string` method returns the path part of the node's location. So if the full path is `/path/to/file.ext` this method returns `/path/to/`.\n\n#### name()\n\nThe `name(): string` method returns the name part of the node's location. So if the full path is `/path/to/file.ext` this method returns `file.ext`.\n\n#### stat()\n\nThe `stat(): PromiseInterface\u003c?Stat\u003e` method stats the node and provides you with information such as its size, full path, create/update time.\n\n### DirectoryInterface\n\n#### ls\n\nThe `ls(): PromiseInterface\u003carray\u003cNodeInterface\u003e\u003e` method list all contents of the given directory and will return an\narray with nodes in it. It will do it's best to detect which type a node is itself, and otherwise fallback\nto `FilesystemInterface::detect(string $path): PromiseInterface\u003cNodeInterface\u003e`.\n\n### FileInterface\n\nThe `*Contents` methods on this interface are designed to behave the same as PHP's `file_(get|put)_contents` functions \nas possible. Resulting in a very familiar API to read/stream from files, or write/append to a file.\n\n#### getContents\n\nFor reading from files `getContents(int $offset = 0 , ?int $maxlen = null): PromiseInterface\u003cstring\u003e` provides two \narguments that control how much data it reads from the file. Without arguments, it will read everything:\n\n```php\n$file-\u003egetContents();\n```\n\nThe offset and maximum length let you 'select' a chunk of the file to be read. The following will skip the first `2048` \nbytes and then read up to `1024` bytes from the file. However, if the file only contains `512` bytes  after the `2048` \noffset it will only return those `512` bytes.\n\n```php\n$file-\u003egetContents(2048, 1024);\n```\n\nIt is possible to tail files with, the following example uses a timer as trigger to check for updates:\n\n```php\n$offset = 0;\nLoop::addPeriodicTimer(1, function (TimerInterface $timer) use ($file, \u0026$offset, $loop): void {\n    $file-\u003egetContents($offset)-\u003ethen(function (string $contents) use (\u0026$offset, $timer, $loop): void {\n        echo $contents; // Echo's the content for example purposes\n        $offset += strlen($contents);\n    });\n});\n```\n\n#### putContents\n\nWriting to file's is `putContents(string $contents, int $flags = 0): PromiseInterface\u003cint\u003e` specialty. By default, when \npassing it contents, it will truncate the file when it exists or create a new one and then fill it with the contents \ngiven.\n\n\n```php\n$file-\u003eputContents('ReactPHP');\n```\n\nAppending files is also supported, by using the `\\FILE_APPEND` constant the file is appended when it exists.\n\n```php\n$file-\u003eputContents(' is awesome!', \\FILE_APPEND);\n```\n\n### NotExistInterface\n\nBoth creation methods will check if the parent directory exists and create it if it doesn't. Effectively making this \ncreation process recursively.\n\n#### createDirectory\n\nThe following will create `lets/make/a/nested/directory` as a recursive directory structure.\n\n```php\n$filesystem-\u003edirectory(\n    __DIR__ . 'lets' . DIRECTORY_SEPARATOR . 'make' . DIRECTORY_SEPARATOR . 'a' . DIRECTORY_SEPARATOR . 'nested' . DIRECTORY_SEPARATOR . 'directory'\n)-\u003ecreateDirectory();\n```\n\n#### createFile\n\nThe following will create `with-a-file.txt` in `lets/make/a/nested/directory` and write `This is amazing!` into that file.\n\n```php\nuse React\\Filesystem\\Node\\FileInterface;\n\n$filesystem-\u003efile(\n    __DIR__ . 'lets' . DIRECTORY_SEPARATOR . 'make' . DIRECTORY_SEPARATOR . 'a' . DIRECTORY_SEPARATOR . 'nested' . DIRECTORY_SEPARATOR . 'directory' . DIRECTORY_SEPARATOR . 'with-a-file.txt'\n)-\u003ecreateFile()-\u003ethen(function (FileInterface $file) {\n    return $file-\u003eputContents('This is amazing!')\n});\n```\n\n## Install\n\nThe recommended way to install this library is [through Composer](https://getcomposer.org).\n[New to Composer?](https://getcomposer.org/doc/00-intro.md)\n\nOnce released, this project will follow [SemVer](https://semver.org/).\nAt the moment, this will install the latest development version:\n\n```bash\ncomposer require react/filesystem:^0.2@dev\n```\n\nSee also the [CHANGELOG](CHANGELOG.md) for details about version upgrades.\n\nThis project aims to run on any platform and thus does not require any PHP \nextensions and supports running on PHP 7.4 through current PHP 8+.\nIt's *highly recommended to use the latest supported PHP version* for this project.\n\nInstalling any of the event loop extensions is suggested, but entirely optional.\nSee also [event loop implementations](#loop-implementations) for more details.\n\n## Tests\n\nTo run the test suite, you first need to clone this repo and then install all\ndependencies [through Composer](https://getcomposer.org):\n\n```bash\ncomposer install\n```\n\nTo run the test suite, go to the project root and run:\n\n```bash\nvendor/bin/phpunit\n```\n\n## License\n\nMIT, see [LICENSE file](LICENSE).\n","funding_links":["https://github.com/sponsors/reactphp","https://github.com/sponsors/clue","https://github.com/sponsors/WyriHaximus","https://opencollective.com/reactphp"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freactphp%2Ffilesystem","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Freactphp%2Ffilesystem","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freactphp%2Ffilesystem/lists"}