Weave 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 Laravel Package

graham-campbell/flysystem

Laravel Flysystem is a Flysystem bridge for Laravel by Graham Campbell, built on Laravel Manager. It provides a unified filesystem manager with support for local, S3, Dropbox, and other storage adapters, requiring PHP 7.4-8.1 and Laravel 8.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install the bridge with the version that matches your Laravel/PHP stack. For Laravel 8 / PHP 7.4–8.1:

    composer require "graham-campbell/flysystem:^8.0"
    

    If you need a non-local adapter, install its Flysystem adapter separately (e.g. league/flysystem-aws-s3-v3:^1.0 for S3, league/flysystem-sftp:^1.0 for SFTP, spatie/flysystem-dropbox:^1.0 for Dropbox). The bridge does not pull those in automatically.

  2. Register the service provider if you are not using package auto-discovery:

    GrahamCampbell\Flysystem\FlysystemServiceProvider::class,
    

    Optionally alias the facade in config/app.php:

    'Flysystem' => GrahamCampbell\Flysystem\Facades\Flysystem::class,
    
  3. Publish the config and edit config/flysystem.php:

    php artisan vendor:publish
    

    Set 'default' to the connection you want the facade to use by default (initially 'local'), define your 'connections' (local, s3, sftp, etc.), and optionally configure 'cache'.

  4. First use case — write and read a file on the default local disk:

    use GrahamCampbell\Flysystem\Facades\Flysystem;
    
    Flysystem::put('hi.txt', 'foo');
    echo Flysystem::read('hi.txt'); // foo
    

    To target another configured connection:

    Flysystem::connection('s3')->put('uploads/photo.jpg', $contents);
    
  5. Where to look first: the published config/flysystem.php (driver examples are inline), the FlysystemManager class (bound as 'flysystem'), and the underlying League Flysystem 1.x API docs. The bridge mainly wires the manager; most day-to-day methods come from \League\Flysystem\Filesystem.

Implementation Patterns

  • Facade vs. dependency injection. For quick scripts and controllers, the facade is fine. For services, jobs, and testable classes, inject GrahamCampbell\Flysystem\FlysystemManager:

    use GrahamCampbell\Flysystem\FlysystemManager;
    
    class FileService
    {
        public function __construct(private FlysystemManager $flysystem) {}
    
        public function store(string $path, string $contents): void
        {
            $this->flysystem->connection('s3')->put($path, $contents);
        }
    }
    

    This avoids facade coupling and makes mocking straightforward.

  • Multiple connections for different concerns. Configure separate disks for user uploads, generated reports, backups, or public assets. Use the connection() method explicitly in code that must not depend on the default:

    Flysystem::connection('local')->put('tmp/report.pdf', $pdf);
    Flysystem::connection('s3')->put('reports/2024/report.pdf', $pdf);
    

    You can also change the default at runtime with Flysystem::setDefaultConnection('s3'), but prefer explicit connections in shared code.

  • Leverage the full Flysystem API. The manager proxies to \League\Flysystem\Filesystem, so you get put, putStream, read, readStream, has, delete, rename, copy, listContents, getMetadata, getMimetype, getSize, getTimestamp, getVisibility, setVisibility, createDir, and deleteDir. Use streaming variants for large files to avoid memory exhaustion:

    $stream = fopen($request->file('upload')->getRealPath(), 'rb');
    Flysystem::connection('s3')->putStream('uploads/'.$filename, $stream);
    
  • Caching for performance. Configure 'cache' to use either the illuminate driver (Laravel cache) or the adapter driver (Flysystem cached adapter). This is useful for remote disks where has(), getMetadata(), and directory listings are expensive. Remember to install league/flysystem-cached-adapter:^1.0 if using the adapter cache. A typical setup wraps the connection’s adapter:

    'cache' => [
        'driver' => 'illuminate',
        'store'  => null, // default cache store
        'ttl'    => 3600,
    ],
    
  • Integrate with Eloquent models. Store relative paths in the database, then resolve the disk at access time. This keeps your model portable across environments:

    class Document extends Model
    {
        public function contents(): string
        {
            return Flysystem::connection($this->disk)->read($this->path);
        }
    }
    
  • Use in queued jobs. Pass the connection name and path into the job, not the manager instance. In the job, call Flysystem::connection($connectionName)->.... This keeps jobs serializable and avoids leaking changed default connections between jobs.

  • Testing. Mock the manager when injecting it, or use a real local connection pointed at a temporary directory. For facades, use Flysystem::shouldReceive('put')->once(). Because the manager is a Laravel Manager instance, you can also swap the default connection to a test-specific local connection during tests.

Gotchas and Tips

  • Version lock-in is severe. v8 requires Laravel 8 and PHP 7.4–8.1 only. Newer Laravel versions should use Laravel’s built-in filesystem instead. Check the compatibility table before upgrading Laravel; the bridge historically lagged behind framework releases.

  • Flysystem 1.x, not 2.x/3.x. The returned object implements \League\Flysystem\FilesystemInterface (Flysystem 1.x). Modern Flysystem 2/3 APIs (FilesystemOperator, writeStream changed signatures, url() support) are not available. Do not copy examples from current Flysystem docs without checking for v1 compatibility.

  • Adapter packages are separate. A connection will fail at resolution time if the required adapter package is missing. Install only the adapters you actually use, and match the major version (^1.0 for most, ^0.1.6 for Azure, ^7.2 for Google Cloud Storage). The README lists the exact packages.

  • Publish and diff config between upgrades. The package explicitly warns to check for changes to the original config file between releases. Keep your config/flysystem.php under version control and diff after each upgrade to avoid missing new options or changed defaults.

  • Default connection changes can leak. In long-running processes (queue workers, Octane, Swoole), setDefaultConnection() persists for the life of the worker. Always use explicit connection('name') calls in jobs, middleware, and services rather than relying on the facade’s implicit default.

  • Local disk permissions. The default 'local' connection points at a root path (typically storage_path('app') or similar). Ensure the directory exists and is writable by the web server/queue user. Permission errors surface as Flysystem exceptions, not Laravel’s usual storage errors.

  • Cache invalidation is your responsibility. The cached adapter handles some invalidation on writes, but stale listings and metadata can still occur, especially when files are modified outside the application (e.g., another service writes to the same S3 bucket). For critical reads, bypass the cache or use a short TTL.

  • No unified URL generation. Flysystem 1.x has no cross-adapter url() method. For S3, you may need to use the AWS SDK directly or the adapter’s underlying client to generate presigned URLs. The bridge does not add URL helpers. Plan for this if you expose files to browsers.

  • Path hygiene. Flysystem paths are relative to the connection root. Avoid leading slashes and .. traversal. Normalize user-supplied paths before passing them to put/read/delete to prevent escaping the intended directory, especially on local disks.

  • Visibility differences across adapters. Local visibility maps to file permissions; S3 maps to ACLs; some adapters ignore it. Setting 'visibility' => 'public' in config may behave differently per driver. Test visibility behaviour per connection rather than assuming consistency.

  • Debugging connection issues. Start with Flysystem::connection('name')->listContents('', true) to verify the adapter is reachable and configured correctly. If it throws, check the adapter package installation, credentials (use env vars), and root/bucket/container names. Enable Laravel’s exception logging to capture the underlying Flysystem exception message, which usually names the missing config key.

  • Extension points are limited. The README notes that internal classes are not intended for public use. The manager itself is extensible via the Laravel Manager package, but custom connectors are not documented. If you need a custom adapter, prefer creating a standard Flysystem adapter and registering it through the config’s driver mapping rather than modifying package internals.

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.
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk