Add and fix heading IDs (#232)

This commit is contained in:
lukinovec 2023-01-06 15:34:04 +01:00 committed by GitHub
parent 8029bdc51c
commit ca5924646d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 17 additions and 17 deletions

View file

@ -32,7 +32,7 @@ DomainTenantResolver::$cacheTTL = 3600;
DomainTenantResolver::$cacheStore = 'redis'; DomainTenantResolver::$cacheStore = 'redis';
``` ```
## Cache invalidation ## Cache invalidation {#cache-invalidation}
Updating and saving a Tenant model's attributes will cause the cached entry for this model to be invalidated when `DomainTenantResolver::$shouldCache` is set to `true`. Updating and saving a Tenant model's attributes will cause the cached entry for this model to be invalidated when `DomainTenantResolver::$shouldCache` is set to `true`.

View file

@ -52,7 +52,7 @@ The `JobPipeline` is a simple, yet **extremely powerful** class that lets you **
You may use a job pipeline like any other listener, so you can register it in the `TenancyServiceProvider`, `EventServiceProvider` using the `$listen` array, or in any other place using `Event::listen()` — up to you. You may use a job pipeline like any other listener, so you can register it in the `TenancyServiceProvider`, `EventServiceProvider` using the `$listen` array, or in any other place using `Event::listen()` — up to you.
## Creating job pipelines {creating-job-pipelines} ## Creating job pipelines {#creating-job-pipelines}
To create a job pipeline, start by specifying the jobs you want to use: To create a job pipeline, start by specifying the jobs you want to use:

View file

@ -30,7 +30,7 @@ If the impersonation succeeds, the token is deleted from the database.
All tokens expire after 60 seconds by default, and this TTL can be customized — see the section at the very bottom. All tokens expire after 60 seconds by default, and this TTL can be customized — see the section at the very bottom.
## Enabling the feature ## Enabling the feature {#enabling-the-feature}
To enable this feature, go to your `config/tenancy.php` file and make sure the following class is in your `features` part of the config: To enable this feature, go to your `config/tenancy.php` file and make sure the following class is in your `features` part of the config:

View file

@ -6,7 +6,7 @@ section: content
# Laravel Nova {#laravel-nova} # Laravel Nova {#laravel-nova}
## In the central app ## In the central app {#in-the-central-app}
If you wish to use Laravel Nova in the central application (to manage tenants), you need to make a small change to the Nova migrations, they expect your model primary keys to always be unsigned big integers, but your tenants might be using `string` ids. If you wish to use Laravel Nova in the central application (to manage tenants), you need to make a small change to the Nova migrations, they expect your model primary keys to always be unsigned big integers, but your tenants might be using `string` ids.

View file

@ -10,7 +10,7 @@ section: content
Laravel Sanctum works with Tenancy out of the box, with the exception of the `sanctum.csrf-cookie` route. You can make some small changes to make the route work. Laravel Sanctum works with Tenancy out of the box, with the exception of the `sanctum.csrf-cookie` route. You can make some small changes to make the route work.
### Making the csrf-cookie route work in the tenant app ### Making the csrf-cookie route work in the tenant app {#csrf-cookie-route-in-tenant-app}
To make the `sanctum.csrf-cookie` route work in the tenant app, do the following: To make the `sanctum.csrf-cookie` route work in the tenant app, do the following:
@ -29,7 +29,7 @@ Route::group(['prefix' => config('sanctum.prefix', 'sanctum')], static function
}); });
``` ```
### Making the csrf-cookie route work both in the central and the tenant app ### Making the csrf-cookie route work both in the central and the tenant app {#csrf-cookie-route-in-both-apps}
To use the `sanctum.csrf-cookie` route in both the central and the tenant apps: To use the `sanctum.csrf-cookie` route in both the central and the tenant apps:

View file

@ -16,7 +16,7 @@ Here's how you can prevent this.
Since the databases are automatically separated, simply using the database as the session driver will make this problem disappear altogether. Since the databases are automatically separated, simply using the database as the session driver will make this problem disappear altogether.
## Storing sessions in Redis {storing-sessions-in-redis} ## Storing sessions in Redis {#storing-sessions-in-redis}
This is the same solution as using the DB session driver. If you use the [`RedisTenancyBootstrapper`]({{ $page->link('tenancy-bootstrappers') }}), your Redis databases will be automatically separated for your tenants, and as such, any sessions stored in those Redis databases will be scoped correctly. This is the same solution as using the DB session driver. If you use the [`RedisTenancyBootstrapper`]({{ $page->link('tenancy-bootstrappers') }}), your Redis databases will be automatically separated for your tenants, and as such, any sessions stored in those Redis databases will be scoped correctly.
@ -24,4 +24,4 @@ This is the same solution as using the DB session driver. If you use the [`Redis
Alternatively, you may use the `Stancl\Tenancy\Middleware\ScopeSessions` middleware on your tenant routes to make sure that any attempts to manipulate the session will result in a 403 unauthorized response. Alternatively, you may use the `Stancl\Tenancy\Middleware\ScopeSessions` middleware on your tenant routes to make sure that any attempts to manipulate the session will result in a 403 unauthorized response.
This will work with all storage drivers, **but only assuming you use a domain per tenant.** If you use path identification, you **need** to store sessions in the database (if using multi-DB tenancy), or you need to use single-DB tenancy (which is probably more common with path identification). This will work with all storage drivers, **but only assuming you use a domain per tenant.** If you use path identification, you **need** to store sessions in the database (if using multi-DB tenancy), or you need to use single-DB tenancy (which is probably more common with path identification).

View file

@ -88,7 +88,7 @@ And this will automatically scope the `Comment::all()` call to the current tenan
# Database considerations {#database-considerations} # Database considerations {#database-considerations}
### Unique indexes {unique-indexes} ### Unique indexes {#unique-indexes}
If you'd have a unique index such as: If you'd have a unique index such as:

View file

@ -33,7 +33,7 @@ The filesystem bootstrapper makes your app's `Storage` facade and the `storage_p
> 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. > 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 ### Storage path helper {#storage-path-helper}
The bootstrapper suffixes the path returned by `storage_path()` to make the helper tenant-aware. The bootstrapper suffixes the path returned by `storage_path()` to make the helper tenant-aware.
@ -46,7 +46,7 @@ Since `storage_path()` will be suffixed, your folder structure will look like th
Logs will be saved in `storage/logs` regardless of any changes to `storage_path()` and regardless of the tenant. Logs will be saved in `storage/logs` regardless of any changes to `storage_path()` and regardless of the tenant.
### Storage facade ### Storage facade {#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 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).
@ -65,7 +65,7 @@ The root of each disk listed in `config('tenancy.filesystem.disks')` will be suf
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`. 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`.
### Assets ### Assets {#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: 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:

View file

@ -51,7 +51,7 @@ class BarCommand extends Command
} }
``` ```
### Custom implementation ### Custom implementation {#custom-implementation}
If you want more control, you may implement this functionality yourself by simply accepting a `tenant_id` argument and then inside `handle()` doing something like this: If you want more control, you may implement this functionality yourself by simply accepting a `tenant_id` argument and then inside `handle()` doing something like this:
```php ```php

View file

@ -16,7 +16,7 @@ The base model has the following features on top of the ones that are necessary
- Data column trait — lets you store arbitrary keys. Attributes that don't exist as columns on your `tenants` table go to the `data` column as serialized JSON. - Data column trait — lets you store arbitrary keys. Attributes that don't exist as columns on your `tenants` table go to the `data` column as serialized JSON.
- Id generation trait — when you don't supply an ID, a random uuid will be generated. An alternative to this would be using AUTOINCREMENT columns. If you wish to use numerical ids, change the `create_tenants_table` migration to use `bigIncrements()` or some such column type, and set `tenancy.id_generator` config to null. That will disable the ID generation altogether, falling back to the database's autoincrement mechanism. - Id generation trait — when you don't supply an ID, a random uuid will be generated. An alternative to this would be using AUTOINCREMENT columns. If you wish to use numerical ids, change the `create_tenants_table` migration to use `bigIncrements()` or some such column type, and set `tenancy.id_generator` config to null. That will disable the ID generation altogether, falling back to the database's autoincrement mechanism.
## Tenant Model ## Tenant Model {#tenant-model}
**Most** applications using this package will want domain/subdomain identification and tenant databases. To do this, create a new model, e.g. `App\Tenant`, that looks like this: **Most** applications using this package will want domain/subdomain identification and tenant databases. To do this, create a new model, e.g. `App\Tenant`, that looks like this:
```php ```php

View file

@ -10,7 +10,7 @@ section: content
TODO: Review TODO: Review
## Events ## Events {#events}
Keep in mind that the package makes heavy use of events, so if you use `Event::fake()` anywhere in your tests, tenancy initialization and related processes might break. Keep in mind that the package makes heavy use of events, so if you use `Event::fake()` anywhere in your tests, tenancy initialization and related processes might break.
@ -30,7 +30,7 @@ Event::fake();
To test your central app, just write normal Laravel tests. To test your central app, just write normal Laravel tests.
## Tenant app {#central-app} ## Tenant app {#tenant-app}
Note: If you're using multi-database tenancy & the automatic mode, it's not possible to use `:memory:` SQLite databases or the `RefreshDatabase` trait due to the switching of default database. Note: If you're using multi-database tenancy & the automatic mode, it's not possible to use `:memory:` SQLite databases or the `RefreshDatabase` trait due to the switching of default database.
@ -55,7 +55,7 @@ class TestCase // extends ...
public function initializeTenancy() public function initializeTenancy()
{ {
$tenant = Tenant::create(); $tenant = Tenant::create();
tenancy()->initialize($tenant); tenancy()->initialize($tenant);
} }