Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Filesystem Laravel Package

fidry/filesystem

Tiny wrapper around Symfony Filesystem providing a FileSystem interface plus handy extras: path escaping for OS separators, real/normalized real path helpers, and consistent temp file/dir creation (incl. custom stream wrappers).

View on GitHub
Deep Wiki
Context7
## Getting Started

### Minimal Setup
1. **Installation**:
   ```bash
   composer require fidry/filesystem

Register the package in config/app.php under providers:

Fidry\FileSystem\FileSystemServiceProvider::class,
  1. 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
    
  2. 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
    

Implementation Patterns

Dependency Injection

  • Bind the Interface: Prefer dependency injection for testability:
    $this->app->bind(FileSystem::class, function () {
        return new NativeFileSystem();
    });
    
  • Read-Only Mode: Use ReadOnlyFileSystem in tests or read-heavy environments:
    $readOnlyFS = new ReadOnlyFileSystem(failOnWrite: true);
    

Path Handling

  • Cross-Platform Paths: Normalize paths for consistency:
    $normalized = FS::normalizedRealPath('C:\Users\Name\file.txt'); // Returns `C:/Users/Name/file.txt`
    
  • Temporary Files/Directories: Generate safe temp files/dirs:
    $tempFile = FS::tmpFile('upload', '.tmp'); // e.g., `/tmp/upload1234.tmp`
    $tempDir = FS::tmpDir('cache'); // e.g., `/tmp/cache5678`
    

Testing

  • TestCase Integration: Extend FileSystemTestCase for isolated tests:
    class MyTest extends FileSystemTestCase {
        public function test_file_operations() {
            FS::dumpFile('test.txt', 'content');
            $this->assertFileExists('test.txt');
        }
    }
    
  • Mocking SplFileInfo: Use SplFileInfoBuilder to avoid verbose mocks:
    $fakeFile = SplFileInfoBuilder::withTestData()
        ->withFile('test.txt')
        ->withContents('mocked')
        ->build();
    

Finder Integration

  • Custom Finder: Create a Finder instance with the package:
    $finder = FS::createFinder()
        ->files()
        ->in(storage_path('app'));
    

Gotchas and Tips

Pitfalls

  1. Path Normalization:

    • realPath() vs. normalizedRealPath(): The former preserves OS-specific separators (e.g., \ on Windows), while the latter forces /.
    • Fix: Use normalizedRealPath() for consistent paths in logs/URLs.
  2. Temporary Files:

    • tmpFile()/tmpDir() may fail if the target directory lacks write permissions.
    • Fix: Specify a custom directory:
      FS::tmpFile('data', '.tmp', storage_path('framework/cache'));
      
  3. Read-Only Mode:

    • ReadOnlyFileSystem silently ignores writes when failOnWrite: false. Enable failOnWrite: true to catch accidental writes in tests.
  4. Symfony Finder SplFileInfo:

    • The getContents() method is deprecated in Symfony 7.1+. Use FS::readFile() instead:
      $content = FS::readFile($filePath);
      

Debugging Tips

  • Path Issues: Use FS::escapePath() to debug cross-platform path inconsistencies.
  • Permission Errors: Check isReadable() before operations:
    if (!FS::isReadable($file)) {
        throw new \RuntimeException("File not readable: {$file}");
    }
    

Extension Points

  1. Custom Stream Wrappers:

    • Override NativeFileSystem to support custom streams (e.g., S3, SFTP):
      class CustomFileSystem extends NativeFileSystem {
          protected function getStreamWrapper(): string {
              return 's3://';
          }
      }
      
  2. Test Isolation:

    • Override getTmpDirPrefix() in FileSystemTestCase to avoid conflicts:
      protected function getTmpDirPrefix(): string {
          return 'myapp_';
      }
      
  3. Legacy Code:

    • Replace deprecated SplFileInfo::getContents() with FS::readFile() in tests:
      $content = FS::readFile($filePath); // Modern alternative
      

Performance

  • Batch Operations: Use 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');
        });
    

Laravel-Specific

  • Storage Integration:
    • Replace Laravel’s Storage::disk() calls for filesystem operations:
      $filesystem = app(FileSystem::class);
      $filesystem->put('file.txt', 'content'); // Uses Laravel’s filesystem adapter
      
  • Artisan Commands:
    • Use FS for CLI scripts to avoid DI overhead:
      use Fidry\FileSystem\FS;
      
      FS::mkdir(storage_path('logs/backup'));
      

---
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope