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

Flysystem Stream Wrapper Laravel Package

m2mtech/flysystem-stream-wrapper

Adds a PHP stream wrapper for Flysystem v2/v3 so you can use fly:// paths with native file functions (file_put_contents, mkdir, etc.). Includes Symfony Lock-based locking plus options to ignore visibility errors and emulate dir metadata.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require m2mtech/flysystem-stream-wrapper
    

    Register the service provider in config/app.php:

    'providers' => [
        // ...
        M2MTech\FlysystemStreamWrapper\FlysystemStreamWrapperServiceProvider::class,
    ],
    
  2. Basic Usage Configure a Flysystem adapter (e.g., local, s3) and bind it to a stream wrapper name (e.g., myfilesystem):

    use M2MTech\FlysystemStreamWrapper\FlysystemStreamWrapper;
    use League\Flysystem\Filesystem;
    
    $filesystem = new Filesystem(/* your adapter */);
    FlysystemStreamWrapper::add('myfilesystem', $filesystem);
    
  3. First Use Case Access files via PHP’s built-in fopen() or file_get_contents():

    $content = file_get_contents('myfilesystem://path/to/file.txt');
    

Implementation Patterns

Common Workflows

  1. Dynamic Adapter Binding Bind adapters at runtime (e.g., in a service container or config loader):

    $adapter = new S3Adapter([/* config */]);
    $filesystem = new Filesystem($adapter);
    FlysystemStreamWrapper::add('s3-bucket', $filesystem);
    
  2. Laravel Integration Use Laravel’s service container to manage bindings:

    $this->app->singleton('flysystem.my-bucket', fn() => new Filesystem($adapter));
    FlysystemStreamWrapper::add('my-bucket', $this->app->make('flysystem.my-bucket'));
    
  3. Stream Wrapper as a Proxy Useful for:

    • Local development (e.g., local:// for public/).
    • Cloud storage (e.g., s3:// for S3).
    • Custom logic (e.g., encrypted:// via a custom adapter).
  4. Stream Wrapper in Blade Serve files directly in views:

    <img src="{{ asset('myfilesystem://images/logo.png') }}" alt="Logo">
    

Integration Tips

  • Cache Adapters: Wrap adapters (e.g., CacheAdapter) for performance.
  • URL Generation: Use Storage::disk('myfilesystem')->url('path') for public URLs.
  • Validation: Sanitize paths to prevent directory traversal (e.g., str_replace('..', '', $path)).
  • PHP 8+ Compatibility: Ensure your Laravel app is updated to PHP 8+ for full compatibility with deprecation fixes in v1.4.1.

Gotchas and Tips

Pitfalls

  1. Stream Wrapper Naming Collisions Avoid conflicts with PHP’s built-in wrappers (e.g., php://, zip://). Prefix custom names (e.g., app_).

  2. Permissions and Ownership Stream wrappers inherit PHP’s file permissions. Ensure:

    • The web server user (e.g., www-data) has access.
    • Adapters (e.g., S3) are configured with correct IAM roles.
  3. Case Sensitivity Some adapters (e.g., S3) are case-sensitive. Normalize paths:

    $path = strtolower($path);
    
  4. Memory Limits Large files may hit PHP’s memory_limit. Use streaming for big files:

    $handle = fopen('myfilesystem://large-file.zip', 'rb');
    while (!feof($handle)) {
        echo fread($handle, 8192);
    }
    fclose($handle);
    
  5. Error Handling Stream wrapper warnings (e.g., missing files) are now collected and handled gracefully due to fixes in v1.4.1. Ensure your error logging is configured to capture these.

Debugging

  • Check Registered Wrappers:
    stream_get_wrappers(); // List all registered wrappers.
    
  • Log Errors: Enable Flysystem’s logging:
    $filesystem->getAdapter()->getLogger()->setHandler(new \Monolog\Handler\StreamHandler(storage_path('logs/flysystem.log')));
    
  • Test Locally: Use local:// for debugging before deploying to cloud storage.

Extension Points

  1. Custom Adapters Extend functionality by creating wrapper-specific adapters:

    class EncryptedAdapter extends LocalAdapter {
        public function read($path) {
            return decrypt(parent::read($path));
        }
    }
    
  2. Middleware Add logic before/after operations:

    $filesystem->addPlugin(new class {
        public function handleRead($path, $contents) {
            return str_replace('secret', '****', $contents);
        }
    });
    
  3. Fallback Adapters Implement fallback logic for missing files:

    $filesystem->addPlugin(new class {
        public function handleListContents($path) {
            if (!$filesystem->has($path)) {
                return ['fallback-file.txt' => new \League\Flysystem\FileAttributes()];
            }
            return $filesystem->listContents($path);
        }
    });
    
  4. Configuration Centralize bindings in config/filesystems.php:

    'stream_wrappers' => [
        'myfilesystem' => [
            'adapter' => 's3',
            'config' => [/* S3 config */],
        ],
    ],
    

    Then load them in a service provider:

    foreach (config('filesystems.stream_wrappers') as $name => $config) {
        $adapter = new $config['adapter']($config['config']);
        FlysystemStreamWrapper::add($name, new Filesystem($adapter));
    }
    

PHP 8+ Compatibility

  • The v1.4.1 release includes fixes for PHP deprecation warnings. Ensure your Laravel application is running on PHP 8+ to leverage these improvements without warnings.
  • If you encounter deprecation warnings in older PHP versions, consider upgrading your PHP environment or check for custom code that may trigger these warnings.
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.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
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