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

league/flysystem

Flysystem is a filesystem abstraction for PHP that lets you work with local disks, S3, FTP, and more through one consistent API. Swap storage backends without changing your code, with adapters, streams, and strong integration across frameworks like Laravel.

View on GitHub
Deep Wiki
Context7
## Getting Started

### Minimal Setup in Laravel
Install via Composer:
```bash
composer require league/flysystem

Register the service provider in config/app.php (Laravel 8+ auto-discovers it):

'providers' => [
    League\Flysystem\FilesystemServiceProvider::class,
],

Publish the config (optional):

php artisan vendor:publish --provider="League\Flysystem\FilesystemServiceProvider"

First Use Case: Local Filesystem

use League\Flysystem\Filesystem;
use League\Flysystem\Local\LocalFilesystemAdapter;

$adapter = new LocalFilesystemAdapter('/path/to/storage', 'public');
$filesystem = new Filesystem($adapter);

// Write a file
$filesystem->write('file.txt', 'Hello, FlySystem!');

// Read a file
$contents = $filesystem->read('file.txt');

// List files
$files = $filesystem->listContents();

First Use Case: S3 Integration

use League\Flysystem\AwsS3v3\AwsS3V3Adapter;
use Aws\S3\S3Client;

$s3 = new S3Client([
    'version' => 'latest',
    'region'  => 'us-east-1',
    'credentials' => [
        'key'    => 'your-key',
        'secret' => 'your-secret',
    ]
]);

$adapter = new AwsS3V3Adapter($s3, 'your-bucket-name');
$filesystem = new Filesystem($adapter);

Implementation Patterns

Common Workflows

File Uploads with Validation

public function uploadFile(Request $request)
{
    $request->validate([
        'file' => 'required|file|max:10240', // 10MB
    ]);

    $file = $request->file('file');
    $path = 'uploads/' . $file->hashName();

    $this->filesystem->writeStream($path, fopen($file->getRealPath(), 'r'));

    return response()->json(['path' => $path]);
}

Directory Operations

// Create directory
$this->filesystem->createDirectory('images/avatars');

// Check if directory exists
if ($this->filesystem->directoryExists('images/avatars')) {
    // List directory contents
    $contents = $this->filesystem->listContents('images/avatars');
}

// Delete directory (recursively)
$this->filesystem->deleteDirectory('images/avatars');

File Metadata and URLs

// Get file metadata
$metadata = $this->filesystem->metadata('file.txt');

// Generate public URL (if supported by adapter)
$url = $this->filesystem->url('file.txt');

// Generate temporary URL (e.g., for S3)
$tempUrl = $this->filesystem->temporaryUrl(
    'file.txt',
    now()->addMinutes(15)
);

File Visibility and Permissions

// Set visibility (e.g., for S3)
$this->filesystem->setVisibility('file.txt', 'public');

// Copy with visibility retention
$this->filesystem->copy(
    'source.txt',
    'destination.txt',
    ['visibility' => 'public']
);

// Move with visibility retention
$this->filesystem->move(
    'source.txt',
    'destination.txt',
    ['visibility' => 'public']
);

Integration with Laravel Storage

Leverage Laravel's built-in storage integration for seamless usage:

// In config/filesystems.php
'disks' => [
    's3' => [
        'driver' => 's3',
        'key'    => env('AWS_ACCESS_KEY_ID'),
        'secret' => env('AWS_SECRET_ACCESS_KEY'),
        'region' => env('AWS_DEFAULT_REGION'),
        'bucket' => env('AWS_BUCKET'),
        'url'    => env('AWS_URL'),
        'endpoint' => env('AWS_ENDPOINT'),
        'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false),
    ],
    'local' => [
        'driver' => 'local',
        'root' => storage_path('app'),
    ],
],

// Usage in code
use Illuminate\Support\Facades\Storage;

$contents = Storage::disk('s3')->get('file.txt');
Storage::disk('local')->put('file.txt', 'Hello, Laravel!');

Mounting Multiple Filesystems

Use MountManager to handle multiple filesystems under a single interface:

use League\Flysystem\MountManager;

$mountManager = new MountManager([
    'local' => new Filesystem(new LocalFilesystemAdapter('/path/to/local', 'public')),
    's3'    => new Filesystem(new AwsS3V3Adapter($s3Client, 'bucket-name')),
]);

// Access filesystems
$localContents = $mountManager->getAdapter('local')->listContents();
$s3Contents   = $mountManager->getAdapter('s3')->listContents();

// Write to specific filesystem
$mountManager->getAdapter('s3')->write('file.txt', 'Content');

Custom Adapters and Decorators

Extend functionality with decorators or custom adapters:

use League\Flysystem\Filesystem;
use League\Flysystem\StorageAttributes;
use League\Flysystem\AdapterInterface;

// Custom decorator to log file operations
class LoggingAdapter implements AdapterInterface
{
    protected $adapter;

    public function __construct(AdapterInterface $adapter)
    {
        $this->adapter = $adapter;
    }

    public function write($path, $contents, StorageAttributes $attributes)
    {
        \Log::info("Writing to $path");
        return $this->adapter->write($path, $contents, $attributes);
    }

    // Implement other AdapterInterface methods...
}

$adapter = new LoggingAdapter(new LocalFilesystemAdapter('/path'));
$filesystem = new Filesystem($adapter);

Async Operations with AsyncAWS

For high-performance async operations with AWS S3:

use League\Flysystem\AsyncAws\AsyncAwsS3Adapter;
use AsyncAws\S3\S3Client;

$s3Client = new S3Client([
    'version' => 'latest',
    'region'  => 'us-east-1',
    'credentials' => [
        'key'    => env('AWS_ACCESS_KEY_ID'),
        'secret' => env('AWS_SECRET_ACCESS_KEY'),
    ],
]);

$adapter = new AsyncAwsS3Adapter($s3Client, 'bucket-name');
$filesystem = new Filesystem($adapter);

// Async write (non-blocking)
$filesystem->write('file.txt', 'Content')->wait();

Gotchas and Tips

Common Pitfalls

Path Handling

  • Issue: Paths are case-sensitive on some filesystems (e.g., Linux) but not on others (e.g., Windows).

  • Fix: Normalize paths using strtolower() or str_replace() if case sensitivity is a concern.

    $path = str_replace('\\', '/', $path); // Ensure forward slashes
    $path = strtolower($path); // Normalize case
    
  • Issue: Double slashes or trailing slashes can cause issues.

  • Fix: Use rtrim() and ltrim() to clean paths:

    $path = rtrim(ltrim($path, '/'), '/');
    

File Permissions

  • Issue: Writing files to a directory may fail if the directory lacks write permissions.

  • Fix: Ensure the directory exists and has the correct permissions:

    if (!$this->filesystem->directoryExists('path/to/dir')) {
        $this->filesystem->createDirectory('path/to/dir');
    }
    
  • Issue: Visibility settings (e.g., public, private) may not apply if the adapter doesn't support them.

  • Fix: Check adapter documentation or use conditional logic:

    if (method_exists($adapter, 'setVisibility')) {
        $adapter->setVisibility('file.txt', 'public');
    }
    

Adapter-Specific Quirks

  • S3: Ensure the bucket exists before writing files. Use doesBucketExist() if available.

  • SFTP: Connection timeouts or authentication failures can silently fail. Use try-catch blocks:

    try {
        $this->filesystem->write('file.txt', 'Content');
    } catch (\League\Flysystem\Exception\ConnectionException $e) {
        \Log::error("SFTP Connection failed: " . $e->getMessage());
    }
    
  • Local: On Windows, ensure the path uses forward slashes (/). Backslashes (\) may cause issues.

Temporary URLs

  • Issue: Temporary URLs may expire or fail if the underlying service (e.g., S3) has restrictions.
  • Fix: Handle exceptions and regenerate URLs as needed:
    try {
        $url = $this->filesystem->temporaryUrl('file.txt', now()->addMinutes(15));
    } catch (\League\Flysystem\Exception\TemporaryUrlNotSupported $e) {
        // Fallback to public URL or generate a new temporary URL
    }
    

Debugging Tips

Enable Verbose Logging

Configure

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
ecotone/kafka
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata