Search by

cloud-castle / file-system

alex-4-17

Безопасная работа с файловой системой для PHP 8.1+: атомарная запись (случайный temp + rename), потоковое и ленивое чтение, символические/жёсткие ссылки, JSON, рекурсивные операции с каталогами, glob, временные пути и лексические операции с путями с защитой от path traversal. Суперсет возможностей S

v1.1.1 2026-07-23 19:00 UTC

This package is auto-updated.

Last update: 2026-09-04 18:23:21 UTC


README

🇷🇺 Русский · 🇬🇧 English · 🇩🇪 Deutsch · 🇫🇷 Français · 🇪🇸 Español · 🇮🇹 Italiano

CloudCastle FileSystem

CloudCastle FileSystem

Packagist Version PHP Version License Total Downloads Monthly Downloads Stars Dependents

Source Release Issues Wiki

PHPStan Psalm PHPMD Code Style Coverage Infection MSI OpenSSF Scorecard

Безопасная работа с файловой системой для PHP 8.1+: атомарная запись, потоковое и построчное чтение, символические/жёсткие ссылки, рекурсивные операции с каталогами, JSON, поиск по glob и лексические операции с путями с выявлением path traversal. Зависимости — только php и ext-fileinfo.

Установка

composer require cloud-castle/file-system

Требуется PHP 8.1+ и расширение fileinfo.

Быстрый старт

<?php

use CloudCastle\FileSystem\FileSystem;
use CloudCastle\FileSystem\Path;

// Атомарная запись (временный файл + rename) — без частично записанных файлов.
FileSystem::write('/var/app/config/app.php', '<?php return ["debug" => false];');

$content = FileSystem::read('/var/app/config/app.php');
$sha256 = FileSystem::hash('/var/app/config/app.php');
$mime = FileSystem::mimeType('/var/app/config/app.php');

// Каталоги.
FileSystem::makeDirectory('/var/app/cache');
$files = FileSystem::allFiles('/var/app');       // рекурсивно, отсортировано
FileSystem::deleteDirectory('/var/app/cache');   // рекурсивно

// JSON, ленивое чтение и замена.
FileSystem::writeJson('/var/app/state.json', ['ready' => true]);
$state = FileSystem::readJson('/var/app/state.json');
foreach (FileSystem::lines('/var/log/app.log') as $line) { /* без загрузки в память */ }

// Ссылки, рекурсивное копирование, glob.
FileSystem::symlink('/var/app/current', '/var/app/releases/42');
FileSystem::copyDirectory('/var/app/skel', '/var/app/new');
$logs = FileSystem::glob('/var/log/*.log');

// Пути (без обращения к диску).
$path = Path::join('/var', 'app', 'config');           // «/var/app/config»
$safe = Path::normalize('/var/data/../../etc');        // «/etc» — виден выход за пределы
$inside = Path::isWithin('/var/app', '/var/app/x');    // true — защита от path traversal
$rel = Path::relative('/var/log', '/var/app');         // «../log»
$base = Path::commonBasePath('/var/www/a', '/var/www/b'); // «/var/www»
<?php

use CloudCastle\FileSystem\Directory;
use CloudCastle\FileSystem\Finder;
use CloudCastle\FileSystem\TemporaryDirectory;

// Текучий поиск: PHP-файлы глубже первого уровня, крупнее 1 КБ, отсортированные.
$found = Finder::create()
    ->files()
    ->name('*.php')
    ->notName('*.blade.php')
    ->depth(1)
    ->filter(static fn (\SplFileInfo $f): bool => $f->getSize() > 1024)
    ->sortByName()
    ->from('/var/app/src')
    ->paths();

// Зеркалирование и сравнение деревьев.
Directory::mirror('/var/app/dist', '/var/www/public');   // назначение = источник
$same = Directory::identical('/var/backup', '/var/app'); // структура + хеши

// Временный каталог с гарантированной автоочисткой (даже при исключении).
$tmp = TemporaryDirectory::make()->deleteWhenDestroyed();
FileSystem::write($tmp->path('report/data.json'), '{}'); // подкаталоги создаются
// ...по выходу из области видимости $tmp каталог удаляется автоматически.

// Рекурсивная смена прав по всему дереву.
FileSystem::chmod('/var/app/cache', 0o750, recursive: true);

Возможности

  • Атомарная запись через временный файл со случайным именем + rename — исключает частично записанные файлы при сбое или гонке.
  • Файлы: чтение, построчное и ленивое (генератор) чтение, запись, запись массива строк (writeLines), атомарное преобразование (atomicUpdate), дозапись в начало/конец, замена подстрок, копирование, перемещение, удаление, touch, chmod; предикаты missing, isReadable, isWritable, isExecutable, type.
  • Потоки: readStream/writeStream — обработка больших файлов без загрузки в память; запись из потока атомарна.
  • JSON: readJson/writeJson с контролем ошибок кодирования.
  • Ссылки: символические и жёсткие ссылки (symlink, hardlink, readlink).
  • Метаданные и права: размер, directorySize, время модификации, хеш (sha256 и др.), checksumEquals (timing-safe), MIME-тип, guessExtension, humanSize, видимость visibility/setVisibility; права chmod/chown/chgrp с рекурсивным применением по дереву (recursive: true); разрешение реального пути через readlink(canonicalize: true) (аналог realpath).
  • Каталоги: создание (рекурсивно), гарантированное существование файла и каталога (ensureFileExists/ensureDirectoryExists), рекурсивные копирование/перемещение/удаление/очистка, листинг файлов и подкаталогов (в т.ч. рекурсивный), поиск по glob и рекурсивный find, isDirectoryEmpty, deleteDirectories.
  • Текучий поиск (Finder): декларативный обход дерева с фильтрами по типу, маскам имени (name/notName), глубине (depth), произвольным предикатам (filter) и сортировкой; результаты — SplFileInfo со всеми метаданными.
  • Операции над деревом (Directory): зеркалирование каталога (mirror — приведение назначения к источнику с удалением лишнего) и сравнение двух деревьев на идентичность структуры и содержимого (identical).
  • Реестр MIME ↔ расширение (MimeTypes): разрешение расширения по MIME-типу и обратно из встроенной таблицы распространённых типов, без внешних зависимостей.
  • Временные ресурсы с автоочисткой (TemporaryDirectory, TemporaryFile): RAII-объекты, гарантированно удаляющие ресурс при разрушении (deleteWhenDestroyed) — даже при исключении; поддержка явного имени и пересоздания (force).
  • Пути: join, normalize, canonicalize, resolve, relative, isWithin (защита от path traversal), makeAbsolute, getRoot, commonBasePath, getHomeDirectory, expandUser (раскрытие ~), segments, unixSlashes, extension, filename, removeExtension, changeExtension, hasExtension, isAbsolute.
  • Безопасность: отклонение байта NUL в путях, случайное имя temp-файла, атомарность, лексическое выявление выхода за каталог, контрактные исключения вместо предупреждений PHP.

Сравнение с аналогами

Все таблицы ниже сгенерированы автоматически из честных сравнительных тестов (benchmarks/compare.php) на ОДИНАКОВОЙ операции для всех аналогов, PHP 8.3.33, без Xdebug.

1. Функциональность

Возможность🏆 CloudCastlesymfonyleagueilluminatenettespatienative¹
Атомарная запись (temp + rename)
Дозапись в начало и конец файла
Хеш и MIME-тип из коробки
Ленивое построчное чтение (генератор)
Потоковая обработка (readStream/writeStream)
JSON: чтение и запись
Символические и жёсткие ссылки
Рекурсивное копирование каталога
Поиск по glob-шаблону
Лексические операции с путями (relative, isWithin)
Временные файлы и каталоги
Рекурсивный листинг файлов
Управление видимостью (visibility)
Нулевые внешние зависимости (кроме ext-fileinfo)
Текучий поиск с фильтрами (Finder)
Зеркалирование каталога (mirror)
Сравнение деревьев на идентичность
RAII-объекты временных ресурсов (автоочистка)
Рекурсивные права (chmod/chown/chgrp по дереву)
Реестр MIME ↔ расширение из коробки
Разрешение реального пути (realpath)
Утилиты путей: корень, общий базовый, домашний каталог
Всего🏆 221048533

2. Безопасность и корректность

Свойство🏆 CloudCastlesymfonyleagueilluminatenettespatienative¹
Атомарная запись (нет частичных файлов при сбое)
Случайное имя временного файла (защита от symlink-атаки)
Отклонение байта NUL в пути
Лексическое выявление path traversal (isWithin)
Дозапись под блокировкой (LOCK_EX)
Timing-safe проверка целостности (checksumEquals)
Контрактные исключения (маркер-интерфейс)
Гарантированная очистка временных ресурсов (RAII)
Всего🏆 8210120

3. Производительность

Рекурсивный листинг 80 файлов дерева, 3 000 раз (минимум из 4).

РешениеВремя (мс)Итог
native¹1 073,3базовый уровень (не библиотека)
🏆 CloudCastle1 092,4быстрейшее среди библиотек
league1 552,3аналог
nette1 684,1аналог
symfony1 713,5аналог
illuminate2 392,9аналог

4. Потребление памяти

_Рабочая память операции: пик рабочего набора на 3 000 листингов после прогрева классов (memory_reset_peakusage, PHP 8.2+) — только аллокации операции, не вес загруженного кода.

РешениеПиковая память (KB)Итог
🏆 league14легчайшее среди библиотек
CloudCastle18аналог
symfony18аналог
native¹19базовый уровень (не библиотека)
nette26аналог
illuminate83аналог

¹ Базовый уровень (нативные вызовы/примитивы без полноты решения) показан для контекста и не претендует на победу среди библиотек-аналогов.

Производительность и память измеряются на рекурсивном листинге дерева (частая операция обхода проекта). Все аналоги приведены к ЭКВИВАЛЕНТНОЙ работе — материализации одного и того же отсортированного списка путей, который allFiles даёт из коробки. Каждая библиотека замеряется в отдельном процессе; память — это пик рабочего набора самой операции после прогрева классов (не вес загруженного кода). league легче по рабочей памяти за счёт ленивого генератора, уступая по функционалу (4 из 22) — осознанный компромисс: детерминированный материализованный список против ленивого потока.

Вывод: CloudCastle FileSystem объединяет возможности пяти популярных пакетов (суперсет по функционалу — 22 из 22), лидирует по безопасности, качеству кода и по скорости обхода дерева среди библиотек, при нулевых внешних зависимостях (кроме ext-fileinfo).

Плюсы и минусы

Плюсы:

  • Самый широкий набор операций из коробки — суперсет (22 из 22 возможностей) Symfony Filesystem, Flysystem, Laravel, Nette и Spatie вместе взятых: атомарная запись, ссылки, JSON, glob, рекурсивные операции и права, ленивое чтение, потоки, текучий поиск (Finder), зеркалирование и сравнение деревьев (Directory), временные ресурсы с автоочисткой (TemporaryDirectory/TemporaryFile), реестр MIME (MimeTypes), богатые лексические операции с путями.
  • Безопасность по умолчанию: атомарность, случайное имя temp-файла, отклонение байта NUL, лексическое выявление path traversal (isWithin), timing-safe проверка целостности, RAII-очистка временных ресурсов, контрактные исключения с маркер-интерфейсом.
  • Нулевые внешние зависимости (только php и ext-fileinfo) — без транзитивного веса и конфликтов версий.
  • 100 % покрытие строк на каждый файл и 100 % Infection MSI; строгий статанализ (PHPStan max, Psalm errorLevel 1, PHPMD, Deptrac, Rector, PSR-12).
  • Быстрее аналогов на обходе дерева за счёт прямого итератора без оверхеда абстракций.

Минусы:

  • Пакет моложе и менее распространён, чем Symfony/Laravel/Flysystem — меньше сторонних материалов и время на нём в проде.
  • Только локальная файловая система: нет адаптеров к облачным хранилищам (S3/FTP/…), как у Flysystem — для мульти-бэкенда используйте Flysystem, а CloudCastle для локальных операций рядом с ним.
  • Статический фасад: удобно и быстро, но при необходимости мокать ввод-вывод в тестах абстрагируйте вызовы за собственный интерфейс.

Когда применять

  • Конфигурация, кэш, сессии, генерация файлов — там, где критична атомарная запись без частично записанных файлов (деплой, сборка артефактов).
  • Финтех и обработка ПД — благодаря защите от path traversal (isWithin), отклонению NUL и случайным именам temp-файлов при загрузке/выгрузке файлов.
  • CLI-инструменты и скрипты сборки — быстрый рекурсивный обход дерева, хеширование, glob, операции с путями без тяжёлых зависимостей.
  • Библиотеки и пакеты — когда нужен богатый файловый API без навязывания пользователю транзитивных зависимостей.
  • Когда лучше взять другое: для работы с облачными хранилищами или единого API поверх нескольких бэкендов — Flysystem; если проект уже целиком на Symfony или Laravel и хватает их файловых компонентов — их и достаточно.

Разработка

composer install
composer check    # линтеры + статический анализ + тесты
composer fix      # автоисправления (Rector, PHP CS Fixer, PHPCBF)
composer ci       # полный CI-пайплайн локально

Полный список команд с описаниями: composer run-script --list.

Документация

Лицензия

MIT © CloudCastle (alex-4-17@yandex.ru)

🇷🇺 Русский · 🇬🇧 English · 🇩🇪 Deutsch · 🇫🇷 Français · 🇪🇸 Español · 🇮🇹 Italiano