Storage Service Override
The storage service override allows you to make Laravels filesystem disks tenant-aware, allowing each tenant to have their own storage location(s)
Introduction
The storage service override is an implementation of Sprouts service override functionality,
that makes Laravel's built-in storage/filesystem service tenant-aware.
The service override is deferrable until the filesystem
(\Illuminate\Filesystem\FilesystemManager
) service is resolved.
It's also bootable.
How it works
The storage service override works by registering a custom filesystem driver called sprout
.
This driver uses
Laravel's scoped filesystem functionality
to automatically prefix a pre-configured disks path using a tenants' resource key.
This service override doesn't replace the original disk, it instead creates a "clone" with a prefixed path, allowing you to use both the tenanted and non-tenanted versions simultaneously, without worrying.
If the current request/process is one where the current tenant changes from one to another, any previously created/loaded tenant-aware disk will be removed from the filesystem manager, to avoid data-leaking between tenants.
Using
To use the storage service override, you must first make sure that it is registered in the services section of the sprout config.
1'services' => [2 \Sprout\Overrides\StorageOverride::class,3],
Once its registered, you need to create a disk within Laravel's filesystem.php
config file,
specifying sprout
as the driver.
1'disks' => [ 2 'local' => [ 3 'driver' => 'local', 4 'root' => storage_path('app'), 5 'throw' => false, 6 ], 7 8 'tenanted' => [ 9 'driver' => 'sprout',10 ],11]
By default, Sprout will clone whichever disk is set as the default,
but if you want to override this, you can provide the name of the disk using the disk
config option.
1'disks' => [ 2 'local' => [ 3 'driver' => 'local', 4 'root' => storage_path('app'), 5 'throw' => false, 6 ], 7 8 'tenanted' => [ 9 'driver' => 'sprout',10 'disk' => 'local',11 ],12]
Alternatively, instead of the name of a filesystem disk, you can provide a disk config which will be used in a similar fashion to Laravel's on-demand disks.
1'disks' => [ 2 'local' => [ 3 'driver' => 'local', 4 'root' => storage_path('app'), 5 'throw' => false, 6 ], 7 8 'tenanted' => [ 9 'driver' => 'sprout',10 'disk' => [11 'driver' => 'local',12 'root' => storage_path('tenants'),13 ],14 ],15]
You cannot nest sprout
driver disks, attempting to do so will cause an exception to be thrown.
Once you have your disk configured, you can use it as you would any other, if the following criteria are met.
- You are currently within multitenanted context
- There is a current tenancy
- The current tenancy has a current tenant
1Storage::disk('tenanted')->put('image.jpg', $content);2 3$contents = Storage::disk('tenanted')->get('image.jpg');4 5// Etc, etc
Considerations
This implementation of a storage service override works based on the idea of separating tenant files by subdirectory. If you require something more complex, like each tenant having their own disk configuration for external services like AWS S3, etc., then it may be worth considering Sprout Bud, a first party package for just such an occasion.