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

php-standard-library/filesystem

Type-safe filesystem helpers for PHP with consistent exception handling. Provides safer wrappers for common file and directory operations, aiming for clearer intent and fewer runtime surprises. Part of the PHP Standard Library ecosystem.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require php-standard-library/filesystem
    

    No Laravel-specific config is needed—this is a standalone package.

  2. First Use Case: Replace a manual file-read operation with type-safe code:

    use PHPStandardLibrary\Filesystem\File;
    
    try {
        $content = File::read('/path/to/file.txt');
        // Process content...
    } catch (FileNotFoundException $e) {
        Log::error("File missing: {$e->getMessage()}");
    }
    
  3. Where to Look First:

    • Core Classes: Focus on File, Directory, and PathResolver for 80% of use cases.
    • Exceptions: Review FileNotFoundException, DirectoryNotFoundException, and PermissionDeniedException for error handling.
    • Events (v6.1.1+): Check FilesystemEvent if you need reactive workflows (e.g., audit logs).

Implementation Patterns

Core Workflows

1. Path Resolution

  • Problem: Hardcoded paths or DIRECTORY_SEPARATOR hacks.
  • Solution: Use PathResolver for project-relative paths:
    $resolver = new PathResolver();
    $path = $resolver->resolveRelativeToProjectRoot('storage/app/temp');
    
  • Laravel Integration: Replace storage_path() calls in services:
    // Before
    $path = storage_path("app/{$id}.json");
    // After
    $path = (new PathResolver())->resolveRelativeToProjectRoot("app/{$id}.json");
    

2. File Operations

  • Read/Write with Safety:
    // Write
    File::write($path, $content, LockStrategy::NON_BLOCKING);
    // Read
    $content = File::read($path);
    
  • Atomic Writes: Use File::atomicWrite() for critical files (e.g., config):
    File::atomicWrite($configPath, $newConfig);
    

3. Directory Management

  • Ensure/Create:
    Directory::ensure('/tmp/uploads')->create();
    
  • List Files Recursively:
    $files = Directory::listFilesRecursively('/path/to/dir');
    

4. Batch Processing

  • Replace Manual Loops:
    $batch = new BatchProcessor();
    $batch->process($files, 20, function ($file) {
        // Process each file
    });
    
  • Queue Jobs: Dispatch jobs in batches to avoid memory issues:
    $batch->process($files, 50, fn($file) => ProcessFileJob::dispatch($file));
    

5. Event-Driven Workflows

  • Audit Logs:
    $filesystem = new Filesystem();
    $filesystem->on('fileCreated', function ($event) {
        Log::info("File created: {$event->getPath()}");
    });
    File::write('/tmp/test.txt', 'content');
    
  • Laravel Bridge: Dispatch Laravel events from package events:
    $filesystem->on('fileCreated', fn($event) =>
        event(new \App\Events\FileCreated($event->getPath()))
    );
    

Integration Tips

With Laravel Services

  • Dependency Injection: Bind the package’s classes in AppServiceProvider:
    $this->app->singleton(PathResolver::class, fn($app) =>
        new PathResolver($app->basePath())
    );
    
  • Artisan Commands: Use for CLI tools:
    use PHPStandardLibrary\Filesystem\Directory;
    
    class ExportCommand extends Command {
        protected $signature = 'export:data';
        public function handle() {
            $exportDir = Directory::ensure(storage_path('exports'))->create();
            // Export logic...
        }
    }
    

With Queue Jobs

  • Batch Processing Jobs:
    class ProcessFilesJob implements ShouldQueue {
        public function handle() {
            $files = Directory::listFilesRecursively(storage_path('uploads'));
            $batch = new BatchProcessor();
            $batch->process($files, 10, fn($file) => $this->processFile($file));
        }
    }
    

Testing

  • Mock Path Resolution:
    $resolver = $this->createMock(PathResolver::class);
    $resolver->method('resolveRelativeToProjectRoot')->willReturn('/mock/path');
    
  • Exception Testing:
    $this->expectException(FileNotFoundException::class);
    File::read('/nonexistent/file.txt');
    

Gotchas and Tips

Pitfalls

  1. Event System Conflicts

    • Issue: The FilesystemEvent dispatcher uses symfony/event-dispatcher, which may conflict with Laravel’s Illuminate/Events.
    • Fix: Alias the dependency in composer.json:
      "extra": {
          "aliases": {
              "symfony/event-dispatcher": "illuminate/events"
          }
      }
      
      Or use Composer’s replace to avoid duplication.
  2. Windows Path Quirks

    • Issue: UNC paths (e.g., \\server\share) may not resolve correctly.
    • Fix: Validate paths before use:
      if (str_starts_with($path, '\\\\')) {
          throw new InvalidPathException("UNC paths not supported");
      }
      
  3. Batch Processor Overhead

    • Issue: BatchProcessor may slow down small datasets (<100 files).
    • Fix: Use manual loops for tiny batches:
      if (count($files) < 50) {
          foreach ($files as $file) { ... }
      } else {
          $batch->process($files, 20, ...);
      }
      
  4. Permission Handling

    • Issue: PermissionDeniedException may not propagate as expected in shared hosting.
    • Fix: Use File::write() with LockStrategy::NON_BLOCKING and retry logic:
      File::write($path, $content, LockStrategy::NON_BLOCKING);
      
  5. Event Dispatching in Loops

    • Issue: Dispatching events for every file in a batch can be memory-intensive.
    • Fix: Batch events or use a debounce pattern:
      $filesystem->on('fileCreated', function ($event) {
          if (rand(0, 100) < 10) { // 10% chance
              Log::info("File created: {$event->getPath()}");
          }
      });
      

Debugging Tips

  1. Path Resolution Issues

    • Debug: Log resolved paths:
      $path = (new PathResolver())->resolveRelativeToProjectRoot('storage/app/temp');
      Log::debug("Resolved path: {$path}");
      
  2. File Locking Conflicts

    • Debug: Use LockStrategy::NON_BLOCKING and check for FileLockedException:
      try {
          File::write($path, $content, LockStrategy::NON_BLOCKING);
      } catch (FileLockedException $e) {
          Log::warning("File locked, retrying...");
          sleep(1);
          retry();
      }
      
  3. Directory Traversal

    • Debug: Use Directory::listFilesRecursively() with depth limits:
      $files = Directory::listFilesRecursively('/path/to/dir', maxDepth: 3);
      

Extension Points

  1. Custom Exceptions

    • Extend base exceptions for domain-specific errors:
      class InvalidMediaFileException extends FileException {}
      
  2. Path Resolver Extensions

    • Add custom root directories:
      $resolver = new PathResolver();
      $resolver->addRootDirectory('/custom/base/path');
      
  3. Event Listeners

    • Create domain-specific listeners:
      $filesystem->on('fileCreated', new LogFileCreationListener());
      
  4. Batch Processor Strategies

    • Implement custom batch strategies (e.g., parallel processing):
      $batch->setStrategy(new ParallelBatchStrategy(4));
      

Configuration Quirks

  1. Default Lock Strategies

    • The package defaults to LockStrategy::BLOCKING for writes, which may block in high-concurrency environments.
    • Fix: Set a default strategy in a service provider:
      File::setDefaultLockStrategy(LockStrategy::NON_BLOCKING);
      
  2. Event Dispatcher Initialization

    • The FilesystemEvent dispatcher requires explicit initialization:
      $dispatcher = new EventDispatcher();
      $filesystem = new Filesystem($dispatcher);
      
  3. **Path

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.
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor