league/flysystem-read-only
Read-only decorator for League Flysystem adapters. Wrap an existing filesystem adapter to prevent writes, deletes, and other mutations while allowing safe read access. Install via composer require league/flysystem-read-only; docs at flysystem.thephpleague.com.
Install the package via Composer:
composer require league/flysystem-read-only
Immediately wrap an existing Flysystem adapter (e.g., Local, S3, FTP) with ReadOnlyStorage to enforce read-only behavior.
use League\Flysystem\ReadOnly\ReadOnlyStorage;
use League\Flysystem\LocalStorage\LocalStorage;
$storage = new LocalStorage('/var/www/public/assets');
$readOnlyStorage = new ReadOnlyStorage($storage);
// Now $readOnlyStorage permits reads but blocks writes
$content = $readOnlyStorage->read('logo.png'); // ✅ Works
$readOnlyStorage->write('new.txt', 'data'); // ❌ Throws WriteOperationDenied
First use case: Securely serve static assets (images, PDFs, etc.) from an S3 bucket or local directory without risk of accidental modification by the application.
ReadOnlyStorage as a thin decorator around any Flysystem adapter—no adapter-specific config changes needed. Ideal for wrapping S3Adapter, LocalAdapter, or FtpAdapter.APP_ENV or feature flags (e.g., production read-only mode):
$storage = match(config('app.read_only')) {
true => new ReadOnlyStorage(new S3Adapter(...)),
default => new S3Adapter(...),
};
Storage::build() or create a custom FilesystemFactory that injects ReadOnlyStorage for specific disks (e.g., assets-read-only disk).WriteOperationDenied (extends FilesystemException). Always catch and log these explicitly—don’t assume silent failure.setVisibility() or copy() may still attempt writes depending on the underlying adapter (e.g., copy() on S3 might trigger a write). Verify behavior for your specific adapter.config() or dotenv for environment control.^3.0)—low star count and minimal commits suggest low churn, but verify compatibility with your Flysystem version (v2 or v3).How can I help you explore Laravel packages today?