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

File Laravel Package

amphp/file

Non-blocking file I/O for PHP 8.1+ in the AMPHP ecosystem. Read/write files or stream via async file handles while keeping apps responsive. Uses multi-process by default, with optional eio/uv/parallel drivers when available.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require amphp/file
    

    Ensure PHP 8.1+ is used.

  2. First Use Case: Read a file asynchronously:

    use Amp\File;
    
    $contents = File\read('/path/to/file.txt');
    echo $contents;
    
  3. Driver Selection:

    • Defaults to ParallelFilesystemDriver (multi-process) if no extensions are installed.
    • Use BlockingFilesystemDriver for single-process blocking I/O (no extensions required).
    • For threading, install ext-eio, ext-uv, or ext-parallel (e.g., pecl install eio).
  4. Where to Look First:

    • API Documentation (official docs).
    • Amp\File namespace for core functions (read, write, openFile, etc.).
    • Amp\File\File class for stream operations (e.g., seek, tell).

Implementation Patterns

Core Workflows

1. File Operations

  • Read/Write Entire Files:

    $contents = Amp\File\read('/path/to/file.txt');
    Amp\File\write('/path/to/file.txt', $newContents);
    
    • Use File\exists() to check existence before operations.
  • Streaming with File Handles:

    $file = Amp\File\openFile('/path/to/large-file.log', 'r');
    Amp\ByteStream\pipe($file, getStdout()); // Stream to stdout
    $file->close();
    

2. Metadata and Organization

  • Batch Metadata Checks:
    if (Amp\File\isFile('/path/to/file.txt') && Amp\File\isWritable('/path/to/file.txt')) {
        Amp\File\changePermissions('/path/to/file.txt', 0644);
    }
    
  • Recursive Directory Creation:
    Amp\File\createDirectoriesRecursively('/path/to/nested/dir');
    

3. Concurrent File Access

  • Locking for Thread Safety:
    $file = Amp\File\openFile('/path/to/config.json', 'r+');
    $file->lock(); // Exclusive lock
    $data = $file->read(1024);
    $file->unlock();
    
  • Non-Blocking Lock Attempts:
    if ($file->tryLock()) {
        // Critical section
        $file->unlock();
    }
    

4. Integration with Laravel

  • Filesystem Adapter: Create a custom Laravel Filesystem adapter wrapping amphp/file:

    use Amp\File;
    use Illuminate\Contracts\Filesystem\Filesystem;
    
    class AmpFilesystem implements Filesystem {
        public function read($path) {
            return File\read(storage_path($path));
        }
        // Implement other methods...
    }
    

    Register in config/filesystems.php:

    'amp' => [
        'driver' => 'amp',
        'root' => storage_path('app'),
    ],
    
  • Async Queue Workers: Use amphp/file in Laravel queues for non-blocking file operations:

    public function handle() {
        $file = Amp\File\openFile(storage_path('logs/async.log'), 'a');
        Amp\ByteStream\pipe($this->data, $file);
    }
    

5. Error Handling

  • Wrap operations in try-catch for Amp\File\FileException:
    try {
        $contents = Amp\File\read('/nonexistent.txt');
    } catch (Amp\File\FileException $e) {
        report($e);
    }
    

Integration Tips

  1. Driver Customization:

    • Override the default driver in your app bootstrap:
      Amp\File\setFilesystemDriver(new Amp\File\BlockingFilesystemDriver());
      
    • Use LimitedWorkerPool to constrain parallel operations:
      use Amp\Worker\LimitedWorkerPool;
      
      $pool = new LimitedWorkerPool(4);
      $driver = new Amp\File\ParallelFilesystemDriver($pool);
      Amp\File\setFilesystemDriver($driver);
      
  2. File Caching:

    • Use FileCache for repeated metadata access:
      $cache = new Amp\File\FileCache();
      $size = $cache->getSize('/path/to/file.txt'); // Cached after first call
      
  3. Symlink Handling:

    • Resolve symlinks before operations:
      $realPath = Amp\File\resolveSymlink('/path/to/symlink');
      
  4. Atomic Operations:

    • Combine lock() with write() for atomic updates:
      $file = Amp\File\openFile('/path/to/atomic.txt', 'r+');
      $file->lock();
      $file->seek(0);
      $file->write('updated');
      $file->unlock();
      

Gotchas and Tips

Pitfalls

  1. Blocking vs. Non-Blocking:

    • BlockingFilesystemDriver uses synchronous PHP functions (e.g., fopen). Avoid mixing with fiber-based code unless explicitly needed.
    • Fix: Prefer ParallelFilesystemDriver or EioFilesystemDriver for async workflows.
  2. File Locking Deadlocks:

    • Forgetting to call unlock() can block other processes indefinitely.
    • Fix: Use tryLock() with timeouts or wrap in finally:
      $file->lock();
      try {
          // Critical section
      } finally {
          $file->unlock();
      }
      
  3. Path Normalization:

    • amphp/file does not normalize paths (e.g., ../ or ./). Use realpath() or Amp\File\resolveSymlink() for safety.
    • Fix:
      $normalized = realpath('/path/with/../segments');
      
  4. Driver-Specific Quirks:

    • ext-uv/ext-eio:
      • May truncate files incorrectly in append mode ('a'). Use 'r+' and seek(0) for updates.
      • Fix: Test with Amp\File\getStatus() to verify behavior.
    • BlockingFilesystemDriver:
      • Not suitable for high-concurrency apps (blocks the event loop).
      • Fix: Use only for simple scripts or fallback.
  5. Fiber Context:

    • File operations must run in a fiber context. Avoid calling from non-fiber code (e.g., CLI scripts without Amp\run).
    • Fix:
      Amp\run(function () {
          $contents = Amp\File\read('/path/to/file.txt');
      });
      
  6. Permission Handling:

    • changePermissions() may fail silently on some systems (e.g., Windows).
    • Fix: Check return values or wrap in try-catch.
  7. Large File Streaming:

    • Always close file handles ($file->close()) to avoid resource leaks.
    • Fix: Use onClose() for cleanup:
      $file->onClose(function () {
          // Cleanup (e.g., log, release resources)
      });
      

Debugging Tips

  1. Log File Operations:

    • Wrap operations in logging:
      try {
          $contents = Amp\File\read('/path/to/file.txt');
          \Log::debug("Read file successfully", ['size' => strlen($contents)]);
      } catch (Throwable $e) {
          \Log::error("File read failed", ['path' => '/path/to/file.txt', 'error' => $e->getMessage()]);
      }
      
  2. Driver-Specific Logging:

    • Enable debug logs for ext-uv/ext-eio:
      putenv('UV_LOGGING=1'); // For ext-uv
      
  3. Check File Handles:

    • Verify handles are not closed prematurely:
      if (!$file->isClosed()) {
          $file->close();
      }
      
  4. Race Conditions:

    • Use KeyedFileMutex for shared resources:
      $mutex = new Amp\File\KeyedFileMutex('/path/to/mutex.lock');
      $guard = $mutex->acquire('key');
      try {
          // Critical section
      } finally {
          $guard->release();
      }
      

Extension Points

  1. Custom File Implementations:
    • Extend Amp\File\File for domain-specific logic (e.g., logging, encryption):
      class LogFile extends Amp\File\File {
          public function write(string $data): void {
              \Log::info
      
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.
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata
splash/openapi