fidry/filesystem
A tiny wrapper around Symfony Filesystem offering a FileSystem interface and utilities for path escaping, real and normalized paths, and temporary files and directories, including support for custom stream wrappers.
Installation:
composer require fidry/filesystem
If your application uses Symfony 8 components, require fidry/filesystem 2.0.1 or later, which adds Symfony 8 support:
composer require fidry/filesystem:^2.0.1
Register the package in config/app.php under providers:
Fidry\FileSystem\FileSystemServiceProvider::class,
Basic Usage:
Bind the FileSystem interface in your service container:
$this->app->bind(FileSystem::class, NativeFileSystem::class);
Or use the static FS helper for quick operations:
use Fidry\FileSystem\FS;
FS::touch('test.txt'); // Creates a file
First Use Case:
Replace Laravel’s native filesystem operations (e.g., Storage::put()) with this package for cross-platform path handling:
$path = FS::escapePath('C:/path/to/file'); // Converts to `C:\path\to\file` on Windows
FS::dumpFile($path, 'Hello, World!'); // Writes content
$this->app->bind(FileSystem::class, function () {
return new NativeFileSystem();
});
ReadOnlyFileSystem in tests or read-heavy environments:
$readOnlyFS = new ReadOnlyFileSystem(failOnWrite: true);
$normalized = FS::normalizedRealPath('C:\Users\Name\file.txt'); // Returns `C:/Users/Name/file.txt`
$tempFile = FS::tmpFile('upload', '.tmp'); // e.g., `/tmp/upload1234.tmp`
$tempDir = FS::tmpDir('cache'); // e.g., `/tmp/cache5678`
FileSystemTestCase for isolated tests:
class MyTest extends FileSystemTestCase {
public function test_file_operations() {
FS::dumpFile('test.txt', 'content');
$this->assertFileExists('test.txt');
}
}
SplFileInfo: Use SplFileInfoBuilder to avoid verbose mocks:
$fakeFile = SplFileInfoBuilder::withTestData()
->withFile('test.txt')
->withContents('mocked')
->build();
Finder instance with the package:
$finder = FS::createFinder()
->files()
->in(storage_path('app'));
fidry/filesystem 2.0.1+, Finder integration is compatible with Symfony 8. If you upgrade Symfony components in a Laravel app, verify the package version resolves correctly:
composer why symfony/finder
composer update fidry/filesystem --with-dependencies
Path Normalization:
realPath() vs. normalizedRealPath(): The former preserves OS-specific separators (e.g., \ on Windows), while the latter forces /.normalizedRealPath() for consistent paths in logs/URLs.Temporary Files:
tmpFile()/tmpDir() may fail if the target directory lacks write permissions.FS::tmpFile('data', '.tmp', storage_path('framework/cache'));
Read-Only Mode:
ReadOnlyFileSystem silently ignores writes when failOnWrite: false. Enable failOnWrite: true to catch accidental writes in tests.Symfony 8 Upgrade Conflicts:
fidry/filesystem may conflict with symfony/finder or related dependencies.fidry/filesystem:^2.0.1 and update dependencies together.Symfony Finder SplFileInfo:
getContents() method is deprecated in Symfony 7.1+. With Symfony 8 support in 2.0.1, prefer FS::readFile() instead:
$content = FS::readFile($filePath);
FS::escapePath() to debug cross-platform path inconsistencies.isReadable() before operations:
if (!FS::isReadable($file)) {
throw new \RuntimeException("File not readable: {$file}");
}
composer show fidry/filesystem
composer why symfony/finder
Custom Stream Wrappers:
NativeFileSystem to support custom streams (e.g., S3, SFTP):
class CustomFileSystem extends NativeFileSystem {
protected function getStreamWrapper(): string {
return 's3://';
}
}
Test Isolation:
getTmpDirPrefix() in FileSystemTestCase to avoid conflicts:
protected function getTmpDirPrefix(): string {
return 'myapp_';
}
Legacy Code:
SplFileInfo::getContents() with FS::readFile() in tests:
$content = FS::readFile($filePath); // Modern alternative
Finder for bulk file operations (e.g., renaming, deleting):
FS::createFinder()
->files()
->in($directory)
->each(function (SplFileInfo $file) {
FS::rename($file->getPathname(), $file->getPathname() . '.bak');
});
Storage::disk() calls for filesystem operations:
$filesystem = app(FileSystem::class);
$filesystem->put('file.txt', 'content'); // Uses Laravel’s filesystem adapter
FS for CLI scripts to avoid DI overhead:
use Fidry\FileSystem\FS;
FS::mkdir(storage_path('logs/backup'));
fidry/filesystem is at least 2.0.1 to avoid dependency resolution issues with Symfony 8.How can I help you explore Laravel packages today?