league/flysystem
Flysystem is a filesystem abstraction for PHP that lets you read, write, and manage files through a unified API across local disks and cloud storage (S3, FTP, SFTP, etc.). Swap adapters without changing app code, with consistent paths, streams, and visibility.
temporaryUrl() for secure, time-limited access to files (e.g., user uploads, collaboration tools).checksum() for data integrity (e.g., backups, financial records).AsyncAwsS3 for non-blocking uploads/downloads to improve performance under load.Adopt When:
Look Elsewhere If:
"FlySystem lets us treat all file storage—local servers, AWS S3, Google Cloud, or even FTP sites—as a single, interchangeable resource. This reduces our infrastructure costs by 20–30% (no more redundant code for each storage type) and future-proofs us for multi-cloud strategies. For example, we can switch a user’s uploads from S3 to Azure Blob Storage with a config change, not a rewrite. It also adds security features like checksum validation and time-limited file sharing out of the box, which aligns with our compliance goals. The package is battle-tested by 13K+ projects, so we’re not betting on unproven tech."
Ask: "Should we prioritize this for our [media library/cloud backup/user uploads] initiative to cut dev time and improve reliability?"
*"FlySystem abstracts away the pain of managing multiple storage backends. Key wins:
if ($storage === 's3') { ... } spaghetti).Trade-offs:
Recommendation: Use FlySystem as the foundation for all file storage in new projects. For legacy systems, start by migrating high-impact modules (e.g., uploads, backups) to reduce technical debt."*
Ask: "Should we allocate a sprint to refactor [X module] using FlySystem, or focus on other priorities?"
*"FlySystem gives you a clean, consistent way to work with files across any storage backend. Here’s how to use it:
Setup:
use League\Flysystem\Filesystem;
use League\Flysystem\Adapter\LocalAdapter;
use League\Flysystem\Adapter\S3v3Adapter;
// Local storage
$localAdapter = new LocalAdapter('/path/to/storage');
$filesystem = new Filesystem($localAdapter);
// AWS S3
$s3Adapter = new S3v3Adapter($client, 'bucket-name');
$s3Fs = new Filesystem($s3Adapter);
Common Operations:
// Upload
$filesystem->write('file.txt', 'Hello, world!');
// Download
$content = $filesystem->read('file.txt');
// Checksum (verify integrity)
$checksum = $filesystem->checksum('file.txt');
// Shareable link (expires in 1 hour)
$url = $filesystem->temporaryUrl('file.txt', now()->addHour());
// Mount multiple backends
$mountManager = new MountManager();
$mountManager->addFilesystem('local', $localFs);
$mountManager->addFilesystem('s3', $s3Fs);
$mountedFs = $mountManager->createFilesystem('s3');
Pro Tips:
MountManager to route files dynamically (e.g., hot files to local, cold to S3).visibility options for S3/GCS to control access (e.g., private by default).disconnectOnDestroy to avoid connection leaks.Why This Matters:
uploadToS3() vs. uploadToLocal()—just call $filesystem->write().Next Steps:
Ask: "Should we document FlySystem patterns in our style guide to standardize file operations across the codebase?"
How can I help you explore Laravel packages today?