consilience/flysystem-azure-file-storage
Flysystem adapter for Azure File Storage that lets Laravel and PHP applications read, write, and manage files on Azure file shares through the familiar Storage API. Configure a disk and use Azure Files like any other filesystem.
This package provides a Laravel filesystem disk driver built on Flysystem v3. Release 1.0.0 is the first Flysystem v3-compatible version, so treat it as a new major line rather than a drop-in replacement for any earlier v1/v2 integration.
Minimum steps:
league/flysystem:^1.0|^2.0composer require vendor/package
php artisan vendor:publish --tag=package-config
config/filesystems.php:
'disks' => [
'package' => [
'driver' => 'package',
// package-specific credentials/options
],
],
use Illuminate\Support\Facades\Storage;
Storage::disk('package')->put('hello.txt', 'hello');
Storage::disk('package')->get('hello.txt');
Storage::disk('package')->fileExists('hello.txt');
Where to look first:
README.md for the supported Laravel/Flysystem matrix.Storage::extend / FilesystemManager::extend).League\Flysystem\FilesystemAdapter.Register the disk via the service provider. Typical Laravel integration creates a Flysystem Filesystem around the package adapter and wraps it in Laravel’s FilesystemAdapter:
Storage::extend('package', function ($app, $config) {
$adapter = new PackageAdapter($config);
$filesystem = new \League\Flysystem\Filesystem($adapter, new \League\Flysystem\Config([
'visibility' => $config['visibility'] ?? 'private',
'directory_visibility' => $config['directory_visibility'] ?? 'private',
]));
return new \Illuminate\Filesystem\FilesystemAdapter($filesystem, $adapter);
});
Use the Storage facade for day-to-day work. Prefer the Laravel API (put, get, exists, delete, url, temporaryUrl, files, allFiles) over calling Flysystem directly. It keeps application code portable across disks.
Use Flysystem directly when you need v3-specific metadata. Laravel’s FilesystemAdapter hides some Flysystem v3 behaviour. For listings and attributes, use the underlying filesystem:
$filesystem = Storage::disk('package')->getDriver();
foreach ($filesystem->listContents('', true) as $item) {
$item->type(); // 'file' or 'dir'
$item->path();
$item->fileSize(); // ?int
$item->mimeType(); // ?string
$item->lastModified(); // int
}
Stream large files. Flysystem v3 treats streams as first-class:
$stream = Storage::disk('package')->readStream('large.zip');
Storage::disk('package')->writeStream('copy.zip', $stream);
Testing pattern. Storage::fake('package') swaps the disk for a local temporary disk, so it validates application logic but not the package adapter. Add at least one integration test that exercises the real driver against a test bucket/container/endpoint. Use Storage::fake() for fast request-level tests and a separate adapter test for listContents, visibility, and error paths.
Upgrade workflow for a Flysystem v2 → v3 move. Run the package’s own tests first, then your application’s storage tests, then a smoke test of the operations your app actually uses (upload, download, temporary URL, delete, listing). Pin the exact version in composer.json until issue #12 is closed:
"vendor/package": "1.0.0"
Feature detection is safer than version sniffing. If you support older and newer versions of the package, wrap calls that only exist in v3 (mimeType(), DirectoryListing, Visibility constants) behind method checks or adapter-level abstractions.
League\Flysystem\FilesystemInterface is gone; use League\Flysystem\Filesystem.getAdapter() is no longer available on the Flysystem object.listContents() returns a DirectoryListing of StorageAttributes (FileAttributes, DirectoryAttributes), not arrays.getMimetype()/getSize()/getTimestamp() style calls became mimeType(), fileSize(), lastModified(), and metadata can be null.UnableToReadFile, UnableToWriteFile, UnableToDeleteFile, UnableToCreateDirectory, etc. Do not catch the old FileNotFoundException hierarchy.League\Flysystem\Visibility constants and a Config object.FilesystemAdapter interface; method signatures and return types must match v3 exactly.Class not found failures.fileExists vs directoryExists. In v3 these are distinct; fileExists() should not be used as a proxy for “path exists”.mimeType(), fileSize(), lastModified(), and visibility can all be null or adapter-dependent. Code that assumes non-null metadata will break on adapters that cannot supply it cheaply... segments in application code; test root-level versus nested paths.Storage::fake() can hide adapter bugs. It replaces the disk entirely. If your application depends on package-specific behaviour (ACLs, custom URLs, eventual consistency), write a real integration test.temporaryUrl() support, verify it against your actual storage backend; a missing or incomplete implementation may only surface at runtime.Config options such as disabling assertion checks can help isolate adapter failures, but do not disable them in production. Inspect the underlying Filesystem directly when FilesystemAdapter hides the failure.Filesystem instance via addPlugin(). If the package wraps the filesystem internally, confirm you can access it (or that the package exposes a way to register plugins); otherwise you may need to construct the adapter yourself.1.0.0, subscribe to the repository, and re-run storage integration tests on every patch release.How can I help you explore Laravel packages today?