From f84ab20c5ecb854cf0892f99967f166960f57f40 Mon Sep 17 00:00:00 2001 From: lukinovec Date: Wed, 28 Sep 2022 15:05:41 +0200 Subject: [PATCH] Update filesystem tenancy documentation (#201) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update filesystem bootstrapper page WIP * Filesystem bootstrapper rewrite * Correct writing * Update 'is not set' to 'is null' * Update the suffix base comment to be more understandable Co-authored-by: Samuel Štancl * Update storage path helper suffix explanation * Improve docs page in response to review * Use the actual suffix instead of the $suffix variable Co-authored-by: Samuel Štancl * Include the file structure tenancy image in the repo * Use the actual suffix instead of the $suffix variable again Co-authored-by: Samuel Štancl * Specify what `asset()` returns Co-authored-by: Samuel Štancl * Restructure assets section * Use 'returned' instead of 'retrieved' Co-authored-by: Samuel Štancl * Apply suggestions from code review Co-authored-by: Samuel Štancl * Say that configuring the asset URL changes the helper's behavior * Update global assets section according to review * Update disabling asset() section according to suggestion * Change 'ID' to 'key' * Update `Storage` facade section * Specify the asset() output with ASSET_URL configured Co-authored-by: Samuel Štancl --- .../assets/images/file_structure_tenancy.png | Bin 0 -> 16948 bytes source/docs/v1/filesystem-tenancy.blade.md | 4 +- source/docs/v2/filesystem-tenancy.blade.md | 2 +- source/docs/v3/tenancy-bootstrappers.blade.md | 85 +++++++++++++----- 4 files changed, 67 insertions(+), 24 deletions(-) create mode 100644 source/assets/images/file_structure_tenancy.png diff --git a/source/assets/images/file_structure_tenancy.png b/source/assets/images/file_structure_tenancy.png new file mode 100644 index 0000000000000000000000000000000000000000..df0f38df83da9d24347d0a6f170719d67a5e3b25 GIT binary patch literal 16948 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 literal 0 HcmV?d00001 diff --git a/source/docs/v1/filesystem-tenancy.blade.md b/source/docs/v1/filesystem-tenancy.blade.md index 499c8dc..dd06d4b 100644 --- a/source/docs/v1/filesystem-tenancy.blade.md +++ b/source/docs/v1/filesystem-tenancy.blade.md @@ -19,7 +19,7 @@ That's what the `root_override` section is for. `%storage_path%` gets replaced b Since `storage_path()` will be suffixed, your folder structure will look like this: -![The folder structure](https://i.imgur.com/GAXQOnN.png) +![The folder structure](/assets/images/file_structure_tenancy.png) If you write to these directories, you will need to create them after you create the tenant. See the docs for [PHP's mkdir](http://php.net/function.mkdir). @@ -49,4 +49,4 @@ Storage::disk('public')->put($filename, $data); Storage::disk('local')->put("public/$filename", $data); ``` -If you want to store something globally, simply create a new disk and *don't* add it to the `tenancy.filesystem.disks` config. \ No newline at end of file +If you want to store something globally, simply create a new disk and *don't* add it to the `tenancy.filesystem.disks` config. diff --git a/source/docs/v2/filesystem-tenancy.blade.md b/source/docs/v2/filesystem-tenancy.blade.md index 59721fa..becbd3d 100644 --- a/source/docs/v2/filesystem-tenancy.blade.md +++ b/source/docs/v2/filesystem-tenancy.blade.md @@ -28,7 +28,7 @@ That's what the `root_override` section is for. `%storage_path%` gets replaced b Since `storage_path()` will be suffixed, your folder structure will look like this: -![The folder structure](https://i.imgur.com/GAXQOnN.png) +![The folder structure](/assets/images/file_structure_tenancy.png) If you write to these directories, you will need to create them after you create the tenant. See the docs for [PHP's mkdir](http://php.net/function.mkdir). diff --git a/source/docs/v3/tenancy-bootstrappers.blade.md b/source/docs/v3/tenancy-bootstrappers.blade.md index 43f81e0..09ac3c5 100644 --- a/source/docs/v3/tenancy-bootstrappers.blade.md +++ b/source/docs/v3/tenancy-bootstrappers.blade.md @@ -29,31 +29,74 @@ php artisan cache:clear --tag=tenant_123 Note that you must use a cache store that supports tagging, e.g. Redis. ## Filesystem tenancy bootstrapper {#filesystem-tenancy-boostrapper} +The filesystem bootstrapper makes your app's `Storage` facade and the `storage_path()` and `asset()` helpers tenant-aware by modifying the paths they return. -This bootstrapper does the following things: +> Note: If you want to bootstrap filesystem tenancy differently (e.g. provision an S3 bucket for each tenant), you can absolutely do that. Take a look at the package's bootstrappers to get an idea of how to write one yourself, and feel free to implement it any way you want. + +### Storage path helper + +The bootstrapper suffixes the path returned by `storage_path()` to make the helper tenant-aware. + +- The suffix is built by appending the tenant key to your `suffix_base`. The `suffix_base` is `tenant` by default, but feel free to change it in the `tenancy.filesystem` config. For example, the suffix will be `tenant42` if the tenant's key is `42` and the `suffix_base` is `tenant`. +- After the suffixing, `storage_path()` helper returns `"/$path_to_your_application/storage/tenant42/"` + +Since `storage_path()` will be suffixed, your folder structure will look like this: + +![The folder structure](/assets/images/file_structure_tenancy.png) + +Logs will be saved in `storage/logs` regardless of any changes to `storage_path()` and regardless of the tenant. + +### Storage facade + +The bootstrapper also makes the `Storage` facade tenant-aware by suffixing the roots of disks listed in `config('tenancy.filesystem.disks')` and by overriding the disk roots in `config('tenancy.filesystem.root_override')` (disk root = the disk path used by the `Storage` facade). + +The root of each disk listed in `config('tenancy.filesystem.disks')` will be suffixed. Doing that alone could cause unwanted behavior since Laravel does its own suffixing, so the filesystem config has the `root_override` section, which lets you override the disk roots **after** tenancy has been initialized: -- Suffixes roots of disks used by the `Storage` facade -- Suffixes `storage_path()` (useful if you're using the local disk for storing tenant files) -- Makes `asset()` calls use the TenantAssetController to retrieve tenant-specific files - - Note: For some assets, e.g. images, you may want to use `global_asset()` (if the asset is shared for all tenants). And for JS/CSS assets, you should use `mix()` or again `global_asset()`. - - Because the `asset()` helper uses the TenantAssetController to retrieve tenant-specific files. Be aware this requires the tenant to be identified and initialized to function. Accordingly, you should ensure that the tenant identification middleware used is appropriate for your use case (defaults to InitializeTenancyByDomain). For example, if you are only using subdomain identification, you should update the middleware used by the TenantAssetController to the InitializeTenancyBySubdomain middleware. To do this, you can follow the steps outlined in [configuration]({{ $page->link('configuration') }}) to update the public static property which defined the middleware used, e.g. in your TenancyServiceProvider: - ```php -use Stancl\Tenancy\Controllers\TenantAssetsController; -use Stancl\Tenancy\Middleware\InitializeTenancyByDomainOrSubdomain; - - // other methods in the TenancyServiceProvider - - public function boot() - { - // update the middleware used by the asset controller - TenantAssetsController::$tenancyMiddleware = InitializeTenancyByDomainOrSubdomain::class; - } +// Tenancy config (tenancy.filesystem.root_override) +// %storage_path% gets replaced by storage_path()'s output +// E.g. Storage::disk('local')->path('') will return "/$path_to_your_application/storage/tenant42/app" +// (Given a suffix_base of 'tenant' and a tenant with a key of `42`. Same as in the example above in the Storage path helper section) +'root_override' => [ + 'local' => '%storage_path%/app/', + 'public' => '%storage_path%/app/public/', +], ``` -This bootstrapper is the most complex one, by far. We will have a — better written — explanation in v3 docs soon, but for now, refer to the 2.x docs for information about filesystem tenancy. [https://tenancyforlaravel.com/docs/v2/filesystem-tenancy/](https://tenancyforlaravel.com/docs/v2/filesystem-tenancy/) +To make the tenant-aware `Storage` facade work with a custom disk, add the disk's name to `config('tenancy.filesystem.disks')` and if the disk is local, override its root in `config('tenancy.filesystem.root_override')` as shown above. With S3, overriding the disk roots is not necessary – `Storage::disk('s3')->path('foo.txt')` will return `/tenant42/foo.txt`. -If you don't want to bootstrap filesystem tenancy in this way, and want to — for example — provision an S3 bucket for each tenant, you can absolutely do that. Look at the package's bootstrappers to get an idea of how to write one yourself, and feel free to implement it any way you want. +### Assets + +The filesystem bootstrapper makes the `asset()` helper link to the files *of the current tenant*. By default, the bootstrapper makes the helper output a URL pointing to the TenantAssetsController (`/tenancy/assets/...`), which returns a file response: + +```php +// TenantAssetsController +return response()->file(storage_path('app/public/' . $path)); +``` + +The package expects the assets to be stored in your tenant's `app/public/` directory. For global assets (non-private assets shared among all tenants), you may want to create a disk and use URLs from that disk instead. For example: + +```php +Storage::disk('branding')->url('header-logo.png'); +``` + +To access global assets such as JS/CSS assets, you can use `global_asset()` and `mix()`. + +Configuring the asset URL (`ASSET_URL` in your `.env`) changes the `asset()` helper's behavior – when the asset URL is set, the bootstrapper will suffix the configured asset URL (the same way `storage_path()` gets suffixed), and make the `asset()` helper output that instead of a path to the TenantAssetsController. + +You can disable tenancy of `asset()` in the config (`tenancy.filesystem.asset_helper_tenancy`) and explicitly use `tenant_asset()` instead. `tenant_asset()` **always** returns a path to the TenantAssetController: `tenant_asset('foo.txt')` returns `your-site.com/tenancy/assets/foo.txt`. You may want to do that if you're facing issues using a package that utilizes `asset()` inside the tenant app. + +Before using the `asset()` helper, make sure to [assign the identification middleware you're using in your app to TenantAssetsController's `$tenancyMiddleware`]({{ $page->link('configuration#static-properties') }}): + +```php +// TenancyServiceProvider (don't forget to import the classes) + +public function boot() +{ + // Update the middleware used by the asset controller + TenantAssetsController::$tenancyMiddleware = InitializeTenancyByDomainOrSubdomain::class; +} +``` ## Queue tenancy bootstrapper {#queue-tenancy-bootstrapper} @@ -87,7 +130,7 @@ class MyBootstrapper implements TenancyBootstrapper { // ... } - + public function revert() { // ... @@ -106,4 +149,4 @@ Then, register it in the `tenancy.bootstrappers` config: App\MyBootstrapper::class, ], -``` \ No newline at end of file +```