From aa5652be4d40ebe09db9732259a8a83612a7ef9a Mon Sep 17 00:00:00 2001 From: Luca Longo Date: Thu, 18 Jul 2024 15:10:01 +0200 Subject: [PATCH 01/17] Contract IsTenant replace Tenant uses --- src/Actions/ForgetCurrentTenantAction.php | 6 +- src/Actions/MakeQueueTenantAwareAction.php | 14 +-- src/Actions/MakeTenantCurrentAction.php | 6 +- src/Actions/MigrateTenantAction.php | 4 +- src/Commands/Concerns/TenantAware.php | 5 +- src/Commands/TenantsArtisanCommand.php | 8 +- src/Concerns/BindAsCurrentTenant.php | 4 +- src/Contracts/IsTenant.php | 19 ++++ src/Events/ForgettingCurrentTenantEvent.php | 4 +- src/Events/ForgotCurrentTenantEvent.php | 4 +- src/Events/MadeTenantCurrentEvent.php | 4 +- src/Events/MakingTenantCurrentEvent.php | 4 +- .../Middleware/EnsureValidTenantSession.php | 4 +- src/Http/Middleware/NeedsTenant.php | 6 +- src/Landlord.php | 6 +- src/Models/Concerns/ImplementsTenant.php | 95 +++++++++++++++++ .../Concerns/UsesLandlordConnection.php | 2 +- src/Models/Concerns/UsesTenantConnection.php | 2 +- src/Models/Concerns/UsesTenantModel.php | 15 --- src/Models/Tenant.php | 100 +----------------- src/Multitenancy.php | 8 +- src/MultitenancyServiceProvider.php | 5 +- src/Tasks/PrefixCacheTask.php | 6 +- src/Tasks/SwitchRouteCacheTask.php | 8 +- src/Tasks/SwitchTenantDatabaseTask.php | 4 +- src/Tasks/SwitchTenantTask.php | 4 +- src/TenantCollection.php | 14 +-- src/TenantFinder/DomainTenantFinder.php | 9 +- src/TenantFinder/TenantFinder.php | 4 +- tests/Feature/Tasks/TestClasses/DummyTask.php | 3 +- 30 files changed, 186 insertions(+), 191 deletions(-) create mode 100644 src/Contracts/IsTenant.php create mode 100644 src/Models/Concerns/ImplementsTenant.php delete mode 100644 src/Models/Concerns/UsesTenantModel.php diff --git a/src/Actions/ForgetCurrentTenantAction.php b/src/Actions/ForgetCurrentTenantAction.php index 26356e14..eb30d41b 100644 --- a/src/Actions/ForgetCurrentTenantAction.php +++ b/src/Actions/ForgetCurrentTenantAction.php @@ -2,9 +2,9 @@ namespace Spatie\Multitenancy\Actions; +use Spatie\Multitenancy\Contracts\IsTenant; use Spatie\Multitenancy\Events\ForgettingCurrentTenantEvent; use Spatie\Multitenancy\Events\ForgotCurrentTenantEvent; -use Spatie\Multitenancy\Models\Tenant; use Spatie\Multitenancy\Tasks\SwitchTenantTask; use Spatie\Multitenancy\Tasks\TasksCollection; @@ -15,7 +15,7 @@ public function __construct( ) { } - public function execute(Tenant $tenant) + public function execute(IsTenant $tenant): void { event(new ForgettingCurrentTenantEvent($tenant)); @@ -33,7 +33,7 @@ protected function performTaskToForgetCurrentTenant(): self return $this; } - protected function clearBoundCurrentTenant() + protected function clearBoundCurrentTenant(): void { $containerKey = config('multitenancy.current_tenant_container_key'); diff --git a/src/Actions/MakeQueueTenantAwareAction.php b/src/Actions/MakeQueueTenantAwareAction.php index 358e93bb..bc4ebce3 100644 --- a/src/Actions/MakeQueueTenantAwareAction.php +++ b/src/Actions/MakeQueueTenantAwareAction.php @@ -6,15 +6,13 @@ use Illuminate\Queue\Events\JobRetryRequested; use Illuminate\Support\Arr; use Spatie\Multitenancy\Concerns\BindAsCurrentTenant; +use Spatie\Multitenancy\Contracts\IsTenant; use Spatie\Multitenancy\Exceptions\CurrentTenantCouldNotBeDeterminedInTenantAwareJob; use Spatie\Multitenancy\Jobs\NotTenantAware; use Spatie\Multitenancy\Jobs\TenantAware; -use Spatie\Multitenancy\Models\Concerns\UsesTenantModel; -use Spatie\Multitenancy\Models\Tenant; class MakeQueueTenantAwareAction { - use UsesTenantModel; use BindAsCurrentTenant; public function execute(): void @@ -34,7 +32,7 @@ protected function listenForJobsBeingQueued(): static return []; } - return ['tenantId' => Tenant::current()?->id]; + return ['tenantId' => app(IsTenant::class)::current()?->getKey()]; }); return $this; @@ -90,7 +88,7 @@ protected function getEventPayload($event): ?array }; } - protected function findTenant(JobProcessing|JobRetryRequested $event): Tenant + protected function findTenant(JobProcessing|JobRetryRequested $event): IsTenant { $tenantId = $this->getEventPayload($event)['tenantId'] ?? null; @@ -100,9 +98,7 @@ protected function findTenant(JobProcessing|JobRetryRequested $event): Tenant throw CurrentTenantCouldNotBeDeterminedInTenantAwareJob::noIdSet($event); } - - /** @var \Spatie\Multitenancy\Models\Tenant $tenant */ - if (! $tenant = $this->getTenantModel()::find($tenantId)) { + if (! $tenant = app(IsTenant::class)::find($tenantId)) { $event->job->delete(); throw CurrentTenantCouldNotBeDeterminedInTenantAwareJob::noTenantFound($event); @@ -134,6 +130,6 @@ protected function bindOrForgetCurrentTenant(JobProcessing|JobRetryRequested $ev return; } - $this->getTenantModel()::forgetCurrent(); + app(IsTenant::class)::forgetCurrent(); } } diff --git a/src/Actions/MakeTenantCurrentAction.php b/src/Actions/MakeTenantCurrentAction.php index 25a88942..fe48e3dd 100644 --- a/src/Actions/MakeTenantCurrentAction.php +++ b/src/Actions/MakeTenantCurrentAction.php @@ -3,9 +3,9 @@ namespace Spatie\Multitenancy\Actions; use Spatie\Multitenancy\Concerns\BindAsCurrentTenant; +use Spatie\Multitenancy\Contracts\IsTenant; use Spatie\Multitenancy\Events\MadeTenantCurrentEvent; use Spatie\Multitenancy\Events\MakingTenantCurrentEvent; -use Spatie\Multitenancy\Models\Tenant; use Spatie\Multitenancy\Tasks\SwitchTenantTask; use Spatie\Multitenancy\Tasks\TasksCollection; @@ -18,7 +18,7 @@ public function __construct( ) { } - public function execute(Tenant $tenant) + public function execute(IsTenant $tenant): static { event(new MakingTenantCurrentEvent($tenant)); @@ -31,7 +31,7 @@ public function execute(Tenant $tenant) return $this; } - protected function performTasksToMakeTenantCurrent(Tenant $tenant): self + protected function performTasksToMakeTenantCurrent(IsTenant $tenant): static { $this->tasksCollection->each(fn (SwitchTenantTask $task) => $task->makeCurrent($tenant)); diff --git a/src/Actions/MigrateTenantAction.php b/src/Actions/MigrateTenantAction.php index 232c6b96..f6fa2dfe 100644 --- a/src/Actions/MigrateTenantAction.php +++ b/src/Actions/MigrateTenantAction.php @@ -3,7 +3,7 @@ namespace Spatie\Multitenancy\Actions; use Illuminate\Support\Facades\Artisan; -use Spatie\Multitenancy\Models\Tenant; +use Spatie\Multitenancy\Contracts\IsTenant; use Symfony\Component\Console\Output\OutputInterface; class MigrateTenantAction @@ -35,7 +35,7 @@ public function output(OutputInterface $output): self return $this; } - public function execute(Tenant $tenant): self + public function execute(IsTenant $tenant): self { $tenant->execute(function () { $migrationCommand = $this->fresh ? 'migrate:fresh' : 'migrate'; diff --git a/src/Commands/Concerns/TenantAware.php b/src/Commands/Concerns/TenantAware.php index d8df9819..e7acce03 100644 --- a/src/Commands/Concerns/TenantAware.php +++ b/src/Commands/Concerns/TenantAware.php @@ -4,20 +4,19 @@ use Illuminate\Support\Arr; use Spatie\Multitenancy\Concerns\UsesMultitenancyConfig; -use Spatie\Multitenancy\Models\Concerns\UsesTenantModel; +use Spatie\Multitenancy\Contracts\IsTenant; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; trait TenantAware { use UsesMultitenancyConfig; - use UsesTenantModel; protected function execute(InputInterface $input, OutputInterface $output): int { $tenants = Arr::wrap($this->option('tenant')); - $tenantQuery = $this->getTenantModel()::query() + $tenantQuery = app(IsTenant::class)::query() ->when(! blank($tenants), function ($query) use ($tenants) { collect($this->getTenantArtisanSearchFields()) ->each(fn ($field) => $query->orWhereIn($field, $tenants)); diff --git a/src/Commands/TenantsArtisanCommand.php b/src/Commands/TenantsArtisanCommand.php index 8cc1c8ff..6c2bc125 100644 --- a/src/Commands/TenantsArtisanCommand.php +++ b/src/Commands/TenantsArtisanCommand.php @@ -6,18 +6,16 @@ use Illuminate\Support\Facades\Artisan; use Spatie\Multitenancy\Commands\Concerns\TenantAware; use Spatie\Multitenancy\Concerns\UsesMultitenancyConfig; -use Spatie\Multitenancy\Models\Concerns\UsesTenantModel; -use Spatie\Multitenancy\Models\Tenant; +use Spatie\Multitenancy\Contracts\IsTenant; class TenantsArtisanCommand extends Command { - use UsesTenantModel; use UsesMultitenancyConfig; use TenantAware; protected $signature = 'tenants:artisan {artisanCommand} {--tenant=*}'; - public function handle() + public function handle(): void { if (! $artisanCommand = $this->argument('artisanCommand')) { $artisanCommand = $this->ask('Which artisan command do you want to run for all tenants?'); @@ -25,7 +23,7 @@ public function handle() $artisanCommand = addslashes($artisanCommand); - $tenant = Tenant::current(); + $tenant = app(IsTenant::class)::current(); $this->line(''); $this->info("Running command for tenant `{$tenant->name}` (id: {$tenant->getKey()})..."); diff --git a/src/Concerns/BindAsCurrentTenant.php b/src/Concerns/BindAsCurrentTenant.php index e12ff74e..1e790c77 100644 --- a/src/Concerns/BindAsCurrentTenant.php +++ b/src/Concerns/BindAsCurrentTenant.php @@ -2,11 +2,11 @@ namespace Spatie\Multitenancy\Concerns; -use Spatie\Multitenancy\Models\Tenant; +use Spatie\Multitenancy\Contracts\IsTenant; trait BindAsCurrentTenant { - protected function bindAsCurrentTenant(Tenant $tenant): self + protected function bindAsCurrentTenant(IsTenant $tenant): self { $containerKey = config('multitenancy.current_tenant_container_key'); diff --git a/src/Contracts/IsTenant.php b/src/Contracts/IsTenant.php new file mode 100644 index 00000000..d00812a2 --- /dev/null +++ b/src/Contracts/IsTenant.php @@ -0,0 +1,19 @@ +session()->has($sessionKey)) { - $request->session()->put($sessionKey, app($this->currentTenantContainerKey())->id); + $request->session()->put($sessionKey, app($this->currentTenantContainerKey())->getKey()); return $next($request); } - if ($request->session()->get($sessionKey) !== app($this->currentTenantContainerKey())->id) { + if ($request->session()->get($sessionKey) !== app($this->currentTenantContainerKey())->getKey()) { return $this->handleInvalidTenantSession($request); } diff --git a/src/Http/Middleware/NeedsTenant.php b/src/Http/Middleware/NeedsTenant.php index 9d460af2..97579cc1 100644 --- a/src/Http/Middleware/NeedsTenant.php +++ b/src/Http/Middleware/NeedsTenant.php @@ -3,16 +3,14 @@ namespace Spatie\Multitenancy\Http\Middleware; use Closure; +use Spatie\Multitenancy\Contracts\IsTenant; use Spatie\Multitenancy\Exceptions\NoCurrentTenant; -use Spatie\Multitenancy\Models\Concerns\UsesTenantModel; class NeedsTenant { - use UsesTenantModel; - public function handle($request, Closure $next) { - if (! $this->getTenantModel()::checkCurrent()) { + if (! app(IsTenant::class)::checkCurrent()) { return $this->handleInvalidRequest(); } diff --git a/src/Landlord.php b/src/Landlord.php index d663b9a8..6f948987 100644 --- a/src/Landlord.php +++ b/src/Landlord.php @@ -2,15 +2,15 @@ namespace Spatie\Multitenancy; -use Spatie\Multitenancy\Models\Tenant; +use Spatie\Multitenancy\Contracts\IsTenant; class Landlord { public static function execute(callable $callable) { - $originalCurrentTenant = Tenant::current(); + $originalCurrentTenant = app(IsTenant::class)::current(); - Tenant::forgetCurrent(); + app(IsTenant::class)::forgetCurrent(); $result = $callable(); diff --git a/src/Models/Concerns/ImplementsTenant.php b/src/Models/Concerns/ImplementsTenant.php new file mode 100644 index 00000000..83911379 --- /dev/null +++ b/src/Models/Concerns/ImplementsTenant.php @@ -0,0 +1,95 @@ +isCurrent()) { + return $this; + } + + static::forgetCurrent(); + + $this + ->getMultitenancyActionClass( + actionName: 'make_tenant_current_action', + actionClass: MakeTenantCurrentAction::class + ) + ->execute($this); + + return $this; + } + + public function forget(): static + { + $this + ->getMultitenancyActionClass( + actionName: 'forget_current_tenant_action', + actionClass: ForgetCurrentTenantAction::class + ) + ->execute($this); + + return $this; + } + + public static function current(): ?static + { + $containerKey = config('multitenancy.current_tenant_container_key'); + + if (! app()->has($containerKey)) { + return null; + } + + return app($containerKey); + } + + public static function checkCurrent(): bool + { + return static::current() !== null; + } + + public function isCurrent(): bool + { + return static::current()?->getKey() === $this->getKey(); + } + + public static function forgetCurrent(): ?static + { + return tap(static::current(), fn (?IsTenant $tenant) => $tenant?->forget()); + } + + public function getDatabaseName(): string + { + return $this->database; + } + + public function newCollection(array $models = []): TenantCollection + { + return new TenantCollection($models); + } + + public function execute(callable $callable): mixed + { + $originalCurrentTenant = static::current(); + + $this->makeCurrent(); + + return tap($callable($this), static function () use ($originalCurrentTenant) { + $originalCurrentTenant + ? $originalCurrentTenant->makeCurrent() + : static::forgetCurrent(); + }); + } + + public function callback(callable $callable): \Closure + { + return fn () => $this->execute($callable); + } +} diff --git a/src/Models/Concerns/UsesLandlordConnection.php b/src/Models/Concerns/UsesLandlordConnection.php index 5da594c6..fa4c1810 100644 --- a/src/Models/Concerns/UsesLandlordConnection.php +++ b/src/Models/Concerns/UsesLandlordConnection.php @@ -8,7 +8,7 @@ trait UsesLandlordConnection { use UsesMultitenancyConfig; - public function getConnectionName() + public function getConnectionName(): ?string { return $this->landlordDatabaseConnectionName(); } diff --git a/src/Models/Concerns/UsesTenantConnection.php b/src/Models/Concerns/UsesTenantConnection.php index d12121aa..df1f760e 100644 --- a/src/Models/Concerns/UsesTenantConnection.php +++ b/src/Models/Concerns/UsesTenantConnection.php @@ -8,7 +8,7 @@ trait UsesTenantConnection { use UsesMultitenancyConfig; - public function getConnectionName() + public function getConnectionName(): ?string { return $this->tenantDatabaseConnectionName(); } diff --git a/src/Models/Concerns/UsesTenantModel.php b/src/Models/Concerns/UsesTenantModel.php deleted file mode 100644 index 9b5de106..00000000 --- a/src/Models/Concerns/UsesTenantModel.php +++ /dev/null @@ -1,15 +0,0 @@ -isCurrent()) { - return $this; - } - - static::forgetCurrent(); - - $this - ->getMultitenancyActionClass( - actionName: 'make_tenant_current_action', - actionClass: MakeTenantCurrentAction::class - ) - ->execute($this); - - return $this; - } - - public function forget(): static - { - $this - ->getMultitenancyActionClass( - actionName: 'forget_current_tenant_action', - actionClass: ForgetCurrentTenantAction::class - ) - ->execute($this); - - return $this; - } - - public static function current(): ?static - { - $containerKey = config('multitenancy.current_tenant_container_key'); - - if (! app()->has($containerKey)) { - return null; - } - - return app($containerKey); - } - - public static function checkCurrent(): bool - { - return static::current() !== null; - } - - public function isCurrent(): bool - { - return static::current()?->getKey() === $this->getKey(); - } - - public static function forgetCurrent(): ?Tenant - { - $currentTenant = static::current(); - - if (is_null($currentTenant)) { - return null; - } - - $currentTenant->forget(); - - return $currentTenant; - } - - public function getDatabaseName(): string - { - return $this->database; - } - - public function newCollection(array $models = []): TenantCollection - { - return new TenantCollection($models); - } - - public function execute(callable $callable) - { - $originalCurrentTenant = Tenant::current(); - - $this->makeCurrent(); - - return tap($callable($this), static function () use ($originalCurrentTenant) { - $originalCurrentTenant - ? $originalCurrentTenant->makeCurrent() - : Tenant::forgetCurrent(); - }); - } - - public function callback(callable $callable): \Closure - { - return fn () => $this->execute($callable); - } } diff --git a/src/Multitenancy.php b/src/Multitenancy.php index 17b631b5..b721559e 100644 --- a/src/Multitenancy.php +++ b/src/Multitenancy.php @@ -5,15 +5,13 @@ use Illuminate\Contracts\Foundation\Application; use Spatie\Multitenancy\Actions\MakeQueueTenantAwareAction; use Spatie\Multitenancy\Concerns\UsesMultitenancyConfig; +use Spatie\Multitenancy\Contracts\IsTenant; use Spatie\Multitenancy\Events\TenantNotFoundForRequestEvent; -use Spatie\Multitenancy\Models\Concerns\UsesTenantModel; -use Spatie\Multitenancy\Models\Tenant; use Spatie\Multitenancy\Tasks\TasksCollection; use Spatie\Multitenancy\TenantFinder\TenantFinder; class Multitenancy { - use UsesTenantModel; use UsesMultitenancyConfig; public function __construct(public Application $app) @@ -31,7 +29,7 @@ public function start(): void public function end(): void { - Tenant::forgetCurrent(); + app(IsTenant::class)::forgetCurrent(); } protected function determineCurrentTenant(): void @@ -45,7 +43,7 @@ protected function determineCurrentTenant(): void $tenant = $tenantFinder->findForRequest($this->app['request']); - if ($tenant instanceof Tenant) { + if ($tenant instanceof IsTenant) { $tenant->makeCurrent(); } else { event(new TenantNotFoundForRequestEvent($this->app['request'])); diff --git a/src/MultitenancyServiceProvider.php b/src/MultitenancyServiceProvider.php index 969de9dd..0606d043 100644 --- a/src/MultitenancyServiceProvider.php +++ b/src/MultitenancyServiceProvider.php @@ -9,11 +9,10 @@ use Spatie\LaravelPackageTools\PackageServiceProvider; use Spatie\Multitenancy\Commands\TenantsArtisanCommand; use Spatie\Multitenancy\Concerns\UsesMultitenancyConfig; -use Spatie\Multitenancy\Models\Concerns\UsesTenantModel; +use Spatie\Multitenancy\Contracts\IsTenant; class MultitenancyServiceProvider extends PackageServiceProvider { - use UsesTenantModel; use UsesMultitenancyConfig; public function configurePackage(Package $package): void @@ -27,6 +26,8 @@ public function configurePackage(Package $package): void public function packageBooted(): void { + $this->app->bind(IsTenant::class, config('multitenancy.tenant_model')); + $this->app->bind(Multitenancy::class, fn ($app) => new Multitenancy($app)); if (! isset($_SERVER['LARAVEL_OCTANE'])) { diff --git a/src/Tasks/PrefixCacheTask.php b/src/Tasks/PrefixCacheTask.php index 783ff33e..765b1fec 100644 --- a/src/Tasks/PrefixCacheTask.php +++ b/src/Tasks/PrefixCacheTask.php @@ -4,7 +4,7 @@ use Illuminate\Cache\Repository; use Illuminate\Support\Facades\Cache; -use Spatie\Multitenancy\Models\Tenant; +use Spatie\Multitenancy\Contracts\IsTenant; class PrefixCacheTask implements SwitchTenantTask { @@ -21,9 +21,9 @@ public function __construct( $this->cacheKeyBase ??= 'tenant_id_'; } - public function makeCurrent(Tenant $tenant): void + public function makeCurrent(IsTenant $tenant): void { - $this->setCachePrefix($this->cacheKeyBase . $tenant->id); + $this->setCachePrefix($this->cacheKeyBase . $tenant->getKey()); } public function forgetCurrent(): void diff --git a/src/Tasks/SwitchRouteCacheTask.php b/src/Tasks/SwitchRouteCacheTask.php index 67f4f4c3..865c136e 100644 --- a/src/Tasks/SwitchRouteCacheTask.php +++ b/src/Tasks/SwitchRouteCacheTask.php @@ -3,11 +3,11 @@ namespace Spatie\Multitenancy\Tasks; use Illuminate\Support\Env; -use Spatie\Multitenancy\Models\Tenant; +use Spatie\Multitenancy\Contracts\IsTenant; class SwitchRouteCacheTask implements SwitchTenantTask { - public function makeCurrent(Tenant $tenant): void + public function makeCurrent(IsTenant $tenant): void { Env::getRepository()->set('APP_ROUTES_CACHE', $this->getCachedRoutesPath($tenant)); @@ -21,13 +21,13 @@ public function forgetCurrent(): void Env::getRepository()->clear('APP_ROUTES_CACHE'); } - protected function getCachedRoutesPath(Tenant $tenant): string + protected function getCachedRoutesPath(IsTenant $tenant): string { if (config('multitenancy.shared_routes_cache')) { return "bootstrap/cache/routes-v7-tenants.php"; } - return "bootstrap/cache/routes-v7-tenant-{$tenant->id}.php"; + return "bootstrap/cache/routes-v7-tenant-{$tenant->getKey()}.php"; } protected function shouldReinitializeRouter(): bool diff --git a/src/Tasks/SwitchTenantDatabaseTask.php b/src/Tasks/SwitchTenantDatabaseTask.php index 4e27e8b2..9b4030c5 100644 --- a/src/Tasks/SwitchTenantDatabaseTask.php +++ b/src/Tasks/SwitchTenantDatabaseTask.php @@ -5,14 +5,14 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Facades\DB; use Spatie\Multitenancy\Concerns\UsesMultitenancyConfig; +use Spatie\Multitenancy\Contracts\IsTenant; use Spatie\Multitenancy\Exceptions\InvalidConfiguration; -use Spatie\Multitenancy\Models\Tenant; class SwitchTenantDatabaseTask implements SwitchTenantTask { use UsesMultitenancyConfig; - public function makeCurrent(Tenant $tenant): void + public function makeCurrent(IsTenant $tenant): void { $this->setTenantConnectionDatabaseName($tenant->getDatabaseName()); } diff --git a/src/Tasks/SwitchTenantTask.php b/src/Tasks/SwitchTenantTask.php index ec21465d..e22d2c0e 100644 --- a/src/Tasks/SwitchTenantTask.php +++ b/src/Tasks/SwitchTenantTask.php @@ -2,11 +2,11 @@ namespace Spatie\Multitenancy\Tasks; -use Spatie\Multitenancy\Models\Tenant; +use Spatie\Multitenancy\Contracts\IsTenant; interface SwitchTenantTask { - public function makeCurrent(Tenant $tenant): void; + public function makeCurrent(IsTenant $tenant): void; public function forgetCurrent(): void; } diff --git a/src/TenantCollection.php b/src/TenantCollection.php index 7ec2159a..f02027e2 100644 --- a/src/TenantCollection.php +++ b/src/TenantCollection.php @@ -3,11 +3,11 @@ namespace Spatie\Multitenancy; use Illuminate\Database\Eloquent\Collection; -use Spatie\Multitenancy\Models\Tenant; +use Spatie\Multitenancy\Contracts\IsTenant; class TenantCollection extends Collection { - public function eachCurrent(callable $callable): self + public function eachCurrent(callable $callable): static { return $this->performCollectionMethodWhileMakingTenantsCurrent( operation: 'each', @@ -15,7 +15,7 @@ public function eachCurrent(callable $callable): self ); } - public function filterCurrent(callable $callable): self + public function filterCurrent(callable $callable): static { return $this->performCollectionMethodWhileMakingTenantsCurrent( operation: 'filter', @@ -23,7 +23,7 @@ public function filterCurrent(callable $callable): self ); } - public function mapCurrent(callable $callable): self + public function mapCurrent(callable $callable): static { return $this->performCollectionMethodWhileMakingTenantsCurrent( operation: 'map', @@ -31,7 +31,7 @@ public function mapCurrent(callable $callable): self ); } - public function rejectCurrent(callable $callable): self + public function rejectCurrent(callable $callable): static { return $this->performCollectionMethodWhileMakingTenantsCurrent( operation: 'reject', @@ -39,9 +39,9 @@ public function rejectCurrent(callable $callable): self ); } - protected function performCollectionMethodWhileMakingTenantsCurrent(string $operation, callable $callable): self + protected function performCollectionMethodWhileMakingTenantsCurrent(string $operation, callable $callable): static { - $collection = $this->$operation(fn (Tenant $tenant) => $tenant->execute($callable)); + $collection = $this->$operation(fn (IsTenant $tenant) => $tenant->execute($callable)); return new static($collection->items); } diff --git a/src/TenantFinder/DomainTenantFinder.php b/src/TenantFinder/DomainTenantFinder.php index 6e4b7cc6..f52fdc18 100644 --- a/src/TenantFinder/DomainTenantFinder.php +++ b/src/TenantFinder/DomainTenantFinder.php @@ -3,17 +3,14 @@ namespace Spatie\Multitenancy\TenantFinder; use Illuminate\Http\Request; -use Spatie\Multitenancy\Models\Concerns\UsesTenantModel; -use Spatie\Multitenancy\Models\Tenant; +use Spatie\Multitenancy\Contracts\IsTenant; class DomainTenantFinder extends TenantFinder { - use UsesTenantModel; - - public function findForRequest(Request $request): ?Tenant + public function findForRequest(Request $request): ?IsTenant { $host = $request->getHost(); - return $this->getTenantModel()::whereDomain($host)->first(); + return app(IsTenant::class)::whereDomain($host)->first(); } } diff --git a/src/TenantFinder/TenantFinder.php b/src/TenantFinder/TenantFinder.php index feb0919c..ab319fee 100644 --- a/src/TenantFinder/TenantFinder.php +++ b/src/TenantFinder/TenantFinder.php @@ -3,9 +3,9 @@ namespace Spatie\Multitenancy\TenantFinder; use Illuminate\Http\Request; -use Spatie\Multitenancy\Models\Tenant; +use Spatie\Multitenancy\Contracts\IsTenant; abstract class TenantFinder { - abstract public function findForRequest(Request $request): ?Tenant; + abstract public function findForRequest(Request $request): ?IsTenant; } diff --git a/tests/Feature/Tasks/TestClasses/DummyTask.php b/tests/Feature/Tasks/TestClasses/DummyTask.php index 8c280f11..96b05dd3 100644 --- a/tests/Feature/Tasks/TestClasses/DummyTask.php +++ b/tests/Feature/Tasks/TestClasses/DummyTask.php @@ -3,6 +3,7 @@ namespace Spatie\Multitenancy\Tests\Feature\Tasks\TestClasses; use Illuminate\Cache\Repository; +use Spatie\Multitenancy\Contracts\IsTenant; use Spatie\Multitenancy\Models\Tenant; use Spatie\Multitenancy\Tasks\SwitchTenantTask; @@ -25,7 +26,7 @@ public function __construct(Repository $config, int $a = 0, int $b = 0) $this->b = $b; } - public function makeCurrent(Tenant $tenant): void + public function makeCurrent(IsTenant $tenant): void { $this->madeCurrentCalled = true; } From ab4a71ec993fa0563d2f05b8a80c2c29c9f66b56 Mon Sep 17 00:00:00 2001 From: masterix21 Date: Thu, 18 Jul 2024 13:10:18 +0000 Subject: [PATCH 02/17] Fix styling --- src/Contracts/IsTenant.php | 10 +++++----- tests/Feature/Tasks/TestClasses/DummyTask.php | 1 - 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/Contracts/IsTenant.php b/src/Contracts/IsTenant.php index d00812a2..822e128d 100644 --- a/src/Contracts/IsTenant.php +++ b/src/Contracts/IsTenant.php @@ -6,14 +6,14 @@ interface IsTenant { - public static function current() : ?static; - public static function checkCurrent() : bool; + public static function current(): ?static; + public static function checkCurrent(): bool; public static function forgetCurrent(): ?static; - public function makeCurrent() : static; - public function forget() : static; + public function makeCurrent(): static; + public function forget(): static; public function isCurrent(): bool; public function getDatabaseName(): string; public function newCollection(array $models = []): TenantCollection; - public function execute(callable $callable) : mixed; + public function execute(callable $callable): mixed; public function callback(callable $callable): \Closure; } diff --git a/tests/Feature/Tasks/TestClasses/DummyTask.php b/tests/Feature/Tasks/TestClasses/DummyTask.php index 96b05dd3..94f0d71e 100644 --- a/tests/Feature/Tasks/TestClasses/DummyTask.php +++ b/tests/Feature/Tasks/TestClasses/DummyTask.php @@ -4,7 +4,6 @@ use Illuminate\Cache\Repository; use Spatie\Multitenancy\Contracts\IsTenant; -use Spatie\Multitenancy\Models\Tenant; use Spatie\Multitenancy\Tasks\SwitchTenantTask; class DummyTask implements SwitchTenantTask From 3bc21447446ecc0c6afe0b66acac439a56057bd5 Mon Sep 17 00:00:00 2001 From: Luca Longo Date: Thu, 18 Jul 2024 15:19:20 +0200 Subject: [PATCH 03/17] Replace self returns to static --- src/Actions/ForgetCurrentTenantAction.php | 2 +- src/Actions/MigrateTenantAction.php | 8 ++++---- src/Concerns/BindAsCurrentTenant.php | 2 +- .../CurrentTenantCouldNotBeDeterminedInTenantAwareJob.php | 2 +- src/Exceptions/InvalidConfiguration.php | 6 +++--- src/Exceptions/TaskCannotBeExecuted.php | 2 +- src/Multitenancy.php | 8 ++++---- 7 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/Actions/ForgetCurrentTenantAction.php b/src/Actions/ForgetCurrentTenantAction.php index eb30d41b..a3ff21c9 100644 --- a/src/Actions/ForgetCurrentTenantAction.php +++ b/src/Actions/ForgetCurrentTenantAction.php @@ -26,7 +26,7 @@ public function execute(IsTenant $tenant): void event(new ForgotCurrentTenantEvent($tenant)); } - protected function performTaskToForgetCurrentTenant(): self + protected function performTaskToForgetCurrentTenant(): static { $this->tasksCollection->each(fn (SwitchTenantTask $task) => $task->forgetCurrent()); diff --git a/src/Actions/MigrateTenantAction.php b/src/Actions/MigrateTenantAction.php index f6fa2dfe..d2988d81 100644 --- a/src/Actions/MigrateTenantAction.php +++ b/src/Actions/MigrateTenantAction.php @@ -14,28 +14,28 @@ class MigrateTenantAction protected OutputInterface $output; - public function fresh(bool $fresh = true): self + public function fresh(bool $fresh = true): static { $this->fresh = $fresh; return $this; } - public function seed(bool $seed = true): self + public function seed(bool $seed = true): static { $this->seed = $seed; return $this; } - public function output(OutputInterface $output): self + public function output(OutputInterface $output): static { $this->output = $output; return $this; } - public function execute(IsTenant $tenant): self + public function execute(IsTenant $tenant): static { $tenant->execute(function () { $migrationCommand = $this->fresh ? 'migrate:fresh' : 'migrate'; diff --git a/src/Concerns/BindAsCurrentTenant.php b/src/Concerns/BindAsCurrentTenant.php index 1e790c77..9ef18d4a 100644 --- a/src/Concerns/BindAsCurrentTenant.php +++ b/src/Concerns/BindAsCurrentTenant.php @@ -6,7 +6,7 @@ trait BindAsCurrentTenant { - protected function bindAsCurrentTenant(IsTenant $tenant): self + protected function bindAsCurrentTenant(IsTenant $tenant): static { $containerKey = config('multitenancy.current_tenant_container_key'); diff --git a/src/Exceptions/CurrentTenantCouldNotBeDeterminedInTenantAwareJob.php b/src/Exceptions/CurrentTenantCouldNotBeDeterminedInTenantAwareJob.php index 6d899381..31025898 100644 --- a/src/Exceptions/CurrentTenantCouldNotBeDeterminedInTenantAwareJob.php +++ b/src/Exceptions/CurrentTenantCouldNotBeDeterminedInTenantAwareJob.php @@ -12,7 +12,7 @@ public static function noIdSet(JobProcessing $event) return new static("The current tenant could not be determined in a job named `" . $event->job->getName() . "`. No `tenantId` was set in the payload."); } - public static function noTenantFound(JobProcessing $event): self + public static function noTenantFound(JobProcessing $event): static { return new static("The current tenant could not be determined in a job named `" . $event->job->getName() . "`. The tenant finder could not find a tenant."); } diff --git a/src/Exceptions/InvalidConfiguration.php b/src/Exceptions/InvalidConfiguration.php index 8448fb6e..6468ed7f 100644 --- a/src/Exceptions/InvalidConfiguration.php +++ b/src/Exceptions/InvalidConfiguration.php @@ -6,17 +6,17 @@ class InvalidConfiguration extends Exception { - public static function tenantConnectionDoesNotExist(string $expectedConnectionName): self + public static function tenantConnectionDoesNotExist(string $expectedConnectionName): static { return new static("Could not find a tenant connection named `{$expectedConnectionName}`. Make sure to create a connection with that name in the `connections` key of the `database` config file."); } - public static function tenantConnectionIsEmptyOrEqualsToLandlordConnection(): self + public static function tenantConnectionIsEmptyOrEqualsToLandlordConnection(): static { return new static("`SwitchTenantDatabaseTask` fails because `multitenancy.tenant_database_connection_name` is `null` or equals to `multitenancy.landlord_database_connection_name`."); } - public static function invalidAction(string $actionName, string $configuredClass, string $actionClass): self + public static function invalidAction(string $actionName, string $configuredClass, string $actionClass): static { return new static("The class currently specified in the `multitenancy.actions.{$actionName}` key '{$configuredClass}' should be or extend `{$actionClass}`."); } diff --git a/src/Exceptions/TaskCannotBeExecuted.php b/src/Exceptions/TaskCannotBeExecuted.php index b192d2c5..1c719ce5 100644 --- a/src/Exceptions/TaskCannotBeExecuted.php +++ b/src/Exceptions/TaskCannotBeExecuted.php @@ -7,7 +7,7 @@ class TaskCannotBeExecuted extends Exception { - public static function make(SwitchTenantTask $task, string $reason): self + public static function make(SwitchTenantTask $task, string $reason): static { $taskClass = $task::class; diff --git a/src/Multitenancy.php b/src/Multitenancy.php index b721559e..ddae7671 100644 --- a/src/Multitenancy.php +++ b/src/Multitenancy.php @@ -50,7 +50,7 @@ protected function determineCurrentTenant(): void } } - protected function registerTasksCollection(): self + protected function registerTasksCollection(): static { $this->app->singleton(TasksCollection::class, function () { $taskClassNames = $this->app['config']->get('multitenancy.switch_tenant_tasks'); @@ -61,7 +61,7 @@ protected function registerTasksCollection(): self return $this; } - protected function registerTenantFinder(): self + protected function registerTenantFinder(): static { $tenantFinderConfig = $this->app['config']->get('multitenancy.tenant_finder'); @@ -72,7 +72,7 @@ protected function registerTenantFinder(): self return $this; } - protected function configureRequests(): self + protected function configureRequests(): static { if (! $this->app->runningInConsole()) { $this->determineCurrentTenant(); @@ -81,7 +81,7 @@ protected function configureRequests(): self return $this; } - protected function configureQueue(): self + protected function configureQueue(): static { $this ->getMultitenancyActionClass( From 6d49defffc808a6303c373160446da88d1496147 Mon Sep 17 00:00:00 2001 From: Luca Longo Date: Thu, 18 Jul 2024 15:34:01 +0200 Subject: [PATCH 04/17] Update multitenancy.php --- config/multitenancy.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/multitenancy.php b/config/multitenancy.php index e0228564..828b8e2d 100644 --- a/config/multitenancy.php +++ b/config/multitenancy.php @@ -42,7 +42,7 @@ /* * This class is the model used for storing configuration on tenants. * - * It must be or extend `Spatie\Multitenancy\Models\Tenant::class` + * It must implement `Spatie\Multitenancy\Contracts\IsTenant::class` interface */ 'tenant_model' => Tenant::class, From 08638895df7c2af6ecda290a1abfbba5af024ba8 Mon Sep 17 00:00:00 2001 From: Luca Longo Date: Thu, 18 Jul 2024 15:35:00 +0200 Subject: [PATCH 05/17] Update multitenancy.php --- config/multitenancy.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config/multitenancy.php b/config/multitenancy.php index 828b8e2d..94e06ed2 100644 --- a/config/multitenancy.php +++ b/config/multitenancy.php @@ -42,7 +42,8 @@ /* * This class is the model used for storing configuration on tenants. * - * It must implement `Spatie\Multitenancy\Contracts\IsTenant::class` interface + * It must extend `Spatie\Multitenancy\Models\Tenant::class` or + * implement `Spatie\Multitenancy\Contracts\IsTenant::class` interface */ 'tenant_model' => Tenant::class, From 5a2169353dd74085620a5043cd7738401571b58f Mon Sep 17 00:00:00 2001 From: Luca Longo Date: Thu, 18 Jul 2024 15:56:14 +0200 Subject: [PATCH 06/17] Update docs --- .../using-a-custom-tenant-model.md | 23 +++++++++++++++++++ ...atically-determining-the-current-tenant.md | 11 ++++----- docs/installation/base-installation.md | 5 ++-- docs/requirements.md | 2 +- 4 files changed, 31 insertions(+), 10 deletions(-) diff --git a/docs/advanced-usage/using-a-custom-tenant-model.md b/docs/advanced-usage/using-a-custom-tenant-model.md index 990f8417..addfdd81 100644 --- a/docs/advanced-usage/using-a-custom-tenant-model.md +++ b/docs/advanced-usage/using-a-custom-tenant-model.md @@ -40,3 +40,26 @@ class CustomTenantModel extends Tenant } } ``` + +## How to create a tenant by any model + +You can't extend our `Tenant` model in many cases. An example could be when you like to use our package with Team features offered by Laravel Jetstream, so your Team model is also your Tenant. + +To accomplish that, you can implement the contract `IsTenant` with our ready-to-use trait `ImplementsTenant`. Take a look at this example: + +```php +namespace App\Models; + +use Laravel\Jetstream\Team as JetstreamTeam; +use Spatie\Multitenancy\Contracts\IsTenant; +use Spatie\Multitenancy\Models\Concerns\ImplementsTenant; + +class Team extends JetstreamTeam implements IsTenant +{ + use HasFactory; + use UsesLandlordConnection; + use ImplementsTenant; +} +``` + +That's all. diff --git a/docs/basic-usage/automatically-determining-the-current-tenant.md b/docs/basic-usage/automatically-determining-the-current-tenant.md index ba7f3f27..6e490b00 100644 --- a/docs/basic-usage/automatically-determining-the-current-tenant.md +++ b/docs/basic-usage/automatically-determining-the-current-tenant.md @@ -28,7 +28,7 @@ app('currentTenant') // will return the current tenant or `null` You can create a tenant finder of your own. A valid tenant finder is any class that extends `Spatie\Multitenancy\TenantFinder\TenantFinder`. You must implement this abstract method: ```php -abstract public function findForRequest(Request $request): ?Tenant; +abstract public function findForRequest(Request $request): ?IsTenant; ``` Here's how the default `DomainTenantFinder` is implemented. The `getTenantModel` returns an instance of the class specified in the `tenant_model` key of the `multitenancy` config file. @@ -37,18 +37,15 @@ Here's how the default `DomainTenantFinder` is implemented. The `getTenantModel` namespace Spatie\Multitenancy\TenantFinder; use Illuminate\Http\Request; -use Spatie\Multitenancy\Models\Concerns\UsesTenantModel; -use Spatie\Multitenancy\Models\Tenant; +use Spatie\Multitenancy\Contracts\IsTenant; class DomainTenantFinder extends TenantFinder { - use UsesTenantModel; - - public function findForRequest(Request $request):?Tenant + public function findForRequest(Request $request): ?IsTenant { $host = $request->getHost(); - return $this->getTenantModel()::whereDomain($host)->first(); + return app(IsTenant::class)::whereDomain($host)->first(); } } ``` diff --git a/docs/installation/base-installation.md b/docs/installation/base-installation.md index 51a7d959..710c6a57 100644 --- a/docs/installation/base-installation.md +++ b/docs/installation/base-installation.md @@ -6,7 +6,7 @@ weight: 1 This package can be installed via composer: ```bash -composer require "spatie/laravel-multitenancy:^3.0" +composer require "spatie/laravel-multitenancy:^4.0" ``` ### Publishing the config file @@ -64,7 +64,8 @@ return [ /* * This class is the model used for storing configuration on tenants. * - * It must be or extend `Spatie\Multitenancy\Models\Tenant::class` + * It must extend `Spatie\Multitenancy\Models\Tenant::class` or + * implement `Spatie\Multitenancy\Contracts\IsTenant::class` interface */ 'tenant_model' => Tenant::class, diff --git a/docs/requirements.md b/docs/requirements.md index e28d6ac3..6476b478 100644 --- a/docs/requirements.md +++ b/docs/requirements.md @@ -3,4 +3,4 @@ title: Requirements weight: 3 --- -This package requires **PHP 8.0+** and **Laravel 8.0+**. +This package requires **PHP 8.2+** and **Laravel 11.0+**. From 2911d53ef90a9108b1c57e79c1679d6eb21b3571 Mon Sep 17 00:00:00 2001 From: Luca Longo Date: Thu, 18 Jul 2024 16:07:57 +0200 Subject: [PATCH 07/17] wip --- docs/advanced-usage/using-tenant-specific-facades.md | 8 ++++---- .../creating-your-own-task.md | 10 ++++------ src/Commands/Concerns/TenantAware.php | 2 +- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/docs/advanced-usage/using-tenant-specific-facades.md b/docs/advanced-usage/using-tenant-specific-facades.md index 3d437e84..46d2110a 100644 --- a/docs/advanced-usage/using-tenant-specific-facades.md +++ b/docs/advanced-usage/using-tenant-specific-facades.md @@ -12,12 +12,12 @@ namespace App\Tenancy\SwitchTasks; use Illuminate\Support\Facades\Facade; use Illuminate\Support\Str; -use Spatie\Multitenancy\Models\Tenant; +use Spatie\Multitenancy\Contracts\IsTenant; use Spatie\Multitenancy\Tasks\SwitchTenantTask; class ClearFacadeInstancesTask implements SwitchTenantTask { - public function makeCurrent(Tenant $tenant): void + public function makeCurrent(IsTenant $tenant): void { // tenant is already current } @@ -43,12 +43,12 @@ namespace App\Tenancy\SwitchTasks; use Illuminate\Support\Facades\Facade; use Illuminate\Support\Str; -use Spatie\Multitenancy\Models\Tenant; +use Spatie\Multitenancy\Contracts\IsTenant; use Spatie\Multitenancy\Tasks\SwitchTenantTask; class ClearFacadeInstancesTask implements SwitchTenantTask { - public function makeCurrent(Tenant $tenant): void + public function makeCurrent(IsTenant $tenant): void { // tenant is already current } diff --git a/docs/using-tasks-to-prepare-the-environment/creating-your-own-task.md b/docs/using-tasks-to-prepare-the-environment/creating-your-own-task.md index b7193cf0..292ed390 100644 --- a/docs/using-tasks-to-prepare-the-environment/creating-your-own-task.md +++ b/docs/using-tasks-to-prepare-the-environment/creating-your-own-task.md @@ -8,11 +8,9 @@ A task is any class that implements `Spatie\Multitenancy\Tasks\SwitchTenantTask` ```php namespace Spatie\Multitenancy\Tasks; -use Spatie\Multitenancy\Models\Tenant; - -interface SwitchTenantTask +use Spatie\Multitenancy\Contracts\IsTenant;interface SwitchTenantTask { - public function makeCurrent(Tenant $tenant): void; + public function makeCurrent(IsTenant $tenant): void; public function forgetCurrent(): void; } @@ -27,7 +25,7 @@ Here is an example implementation where we are going to use a prefix when a tena ```php namespace Spatie\Multitenancy\Tasks; -use Spatie\Multitenancy\Models\Tenant; +use Spatie\Multitenancy\Contracts\IsTenant; class PrefixCacheTask implements SwitchTenantTask { @@ -36,7 +34,7 @@ class PrefixCacheTask implements SwitchTenantTask $this->originalPrefix ??= config('cache.prefix'); } - public function makeCurrent(Tenant $tenant): void + public function makeCurrent(IsTenant $tenant): void { $this->setCachePrefix("tenant_{$tenant->id}"); } diff --git a/src/Commands/Concerns/TenantAware.php b/src/Commands/Concerns/TenantAware.php index e7acce03..2373df83 100644 --- a/src/Commands/Concerns/TenantAware.php +++ b/src/Commands/Concerns/TenantAware.php @@ -30,7 +30,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int return $tenantQuery ->cursor() - ->map(fn ($tenant) => $tenant->execute(fn () => (int) $this->laravel->call([$this, 'handle']))) + ->map(fn (IsTenant $tenant) => $tenant->execute(fn () => (int) $this->laravel->call([$this, 'handle']))) ->sum(); } } From 61ac55bb911e416051ac71c07db637676061a2d3 Mon Sep 17 00:00:00 2001 From: Luca Longo Date: Thu, 18 Jul 2024 16:12:12 +0200 Subject: [PATCH 08/17] wip --- docs/requirements.md | 2 +- src/Tasks/PrefixCacheTask.php | 2 +- src/Tasks/SwitchTenantDatabaseTask.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/requirements.md b/docs/requirements.md index 6476b478..c1318d76 100644 --- a/docs/requirements.md +++ b/docs/requirements.md @@ -3,4 +3,4 @@ title: Requirements weight: 3 --- -This package requires **PHP 8.2+** and **Laravel 11.0+**. +This package requires **PHP 8.2+** and **Laravel 10.0+**. diff --git a/src/Tasks/PrefixCacheTask.php b/src/Tasks/PrefixCacheTask.php index 765b1fec..b5fc531b 100644 --- a/src/Tasks/PrefixCacheTask.php +++ b/src/Tasks/PrefixCacheTask.php @@ -31,7 +31,7 @@ public function forgetCurrent(): void $this->setCachePrefix($this->originalPrefix); } - protected function setCachePrefix(string $prefix) + protected function setCachePrefix(string $prefix): void { config()->set('cache.prefix', $prefix); diff --git a/src/Tasks/SwitchTenantDatabaseTask.php b/src/Tasks/SwitchTenantDatabaseTask.php index 9b4030c5..2d7a19be 100644 --- a/src/Tasks/SwitchTenantDatabaseTask.php +++ b/src/Tasks/SwitchTenantDatabaseTask.php @@ -22,7 +22,7 @@ public function forgetCurrent(): void $this->setTenantConnectionDatabaseName(null); } - protected function setTenantConnectionDatabaseName(?string $databaseName) + protected function setTenantConnectionDatabaseName(?string $databaseName): void { $tenantConnectionName = $this->tenantDatabaseConnectionName(); From ff8970dbae2d9b081e81096014466c77f68476b8 Mon Sep 17 00:00:00 2001 From: Freek Van der Herten Date: Thu, 18 Jul 2024 16:22:08 +0200 Subject: [PATCH 09/17] Update using-a-custom-tenant-model.md --- .../using-a-custom-tenant-model.md | 53 ++++++++++--------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/docs/advanced-usage/using-a-custom-tenant-model.md b/docs/advanced-usage/using-a-custom-tenant-model.md index addfdd81..cb30efed 100644 --- a/docs/advanced-usage/using-a-custom-tenant-model.md +++ b/docs/advanced-usage/using-a-custom-tenant-model.md @@ -3,7 +3,12 @@ title: Using a custom tenant model weight: 6 --- -If you want to change or add behaviour on the `Tenant` model you can use your custom model. Make sure that your custom model extends the `Spatie\Multitenancy\Models\Tenant` model provided by the package. +If you want to change or add behaviour on the `Tenant` model you can use your custom model. There are two ways of doing this by extending the `Tenant` model provided by the package, or by prepping a model of your own. + +## Option 1: extending the `Tenant` model provided by the package + + +Make sure that your custom model extends the `Spatie\Multitenancy\Models\Tenant` model provided by the package. You should specify the class name of your model in the `tenant_model` key of the `multitenancy` config file. @@ -16,6 +21,29 @@ You should specify the class name of your model in the `tenant_model` key of the 'tenant_model' => \App\Models\CustomTenantModel::class, ``` +## Option 2: using a model of your own + +You don't have to extend our `Tenant` model. For example if you use Laravel Jetstream, then you probably want to use `Team` model provided by that package as your tenant model. + +To accomplish that, you can implement the `IsTenant` interface and use trait `ImplementsTenant` to fulfill that intervace. + +Here's an example: + +```php +namespace App\Models; + +use Laravel\Jetstream\Team as JetstreamTeam; +use Spatie\Multitenancy\Contracts\IsTenant; +use Spatie\Multitenancy\Models\Concerns\ImplementsTenant; + +class Team extends JetstreamTeam implements IsTenant +{ + use HasFactory; + use UsesLandlordConnection; + use ImplementsTenant; +} +``` + ## Performing actions when a tenant gets created You can leverage Eloquent's lifecycle callbacks to execute extra logic when a tenant gets created, updated, deleted, ... @@ -40,26 +68,3 @@ class CustomTenantModel extends Tenant } } ``` - -## How to create a tenant by any model - -You can't extend our `Tenant` model in many cases. An example could be when you like to use our package with Team features offered by Laravel Jetstream, so your Team model is also your Tenant. - -To accomplish that, you can implement the contract `IsTenant` with our ready-to-use trait `ImplementsTenant`. Take a look at this example: - -```php -namespace App\Models; - -use Laravel\Jetstream\Team as JetstreamTeam; -use Spatie\Multitenancy\Contracts\IsTenant; -use Spatie\Multitenancy\Models\Concerns\ImplementsTenant; - -class Team extends JetstreamTeam implements IsTenant -{ - use HasFactory; - use UsesLandlordConnection; - use ImplementsTenant; -} -``` - -That's all. From 57b0a8d90be75e957591698d128f0c027f745b19 Mon Sep 17 00:00:00 2001 From: Luca Longo Date: Thu, 18 Jul 2024 16:27:39 +0200 Subject: [PATCH 10/17] Drop support for Laravel 10.x --- .github/workflows/run-tests.yml | 2 +- composer.json | 6 +++--- docs/requirements.md | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index fb2c2b33..44a8220f 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -13,7 +13,7 @@ jobs: matrix: os: [ubuntu-latest] php: [8.2] - laravel: ['10.*', '11.*'] + laravel: ['11.*'] dependency-version: [prefer-lowest, prefer-stable] diff --git a/composer.json b/composer.json index 5c15e92a..932bddb4 100644 --- a/composer.json +++ b/composer.json @@ -17,15 +17,15 @@ ], "require": { "php": "^8.2", - "illuminate/support": "^10.0|^11.0", + "illuminate/support": "^11.0", "spatie/laravel-package-tools": "^1.9" }, "require-dev": { "laravel/legacy-factories": "^1.0.4", - "laravel/octane": "^2.3", + "laravel/octane": "^2.5", "laravel/serializable-closure": "^1.1", "mockery/mockery": "^1.4", - "orchestra/testbench": "^8.0|^9.0", + "orchestra/testbench": "^9.0", "pestphp/pest": "^2.34", "spatie/valuestore": "^1.2" }, diff --git a/docs/requirements.md b/docs/requirements.md index c1318d76..6476b478 100644 --- a/docs/requirements.md +++ b/docs/requirements.md @@ -3,4 +3,4 @@ title: Requirements weight: 3 --- -This package requires **PHP 8.2+** and **Laravel 10.0+**. +This package requires **PHP 8.2+** and **Laravel 11.0+**. From f79dd6be67a21d7dceb02819bc4933353082e876 Mon Sep 17 00:00:00 2001 From: Luca Longo Date: Thu, 18 Jul 2024 17:03:28 +0200 Subject: [PATCH 11/17] Upgrade guide --- docs/requirements.md | 2 +- docs/support-us.md | 2 +- docs/upgrade-guide.md | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 docs/upgrade-guide.md diff --git a/docs/requirements.md b/docs/requirements.md index 6476b478..b358b1e5 100644 --- a/docs/requirements.md +++ b/docs/requirements.md @@ -1,6 +1,6 @@ --- title: Requirements -weight: 3 +weight: 4 --- This package requires **PHP 8.2+** and **Laravel 11.0+**. diff --git a/docs/support-us.md b/docs/support-us.md index 2a1b8ea8..9a404046 100644 --- a/docs/support-us.md +++ b/docs/support-us.md @@ -1,6 +1,6 @@ --- title: Support us -weight: 2 +weight: 3 --- We invest a lot of resources into creating our [best in class open source packages](https://spatie.be/open-source). You can support us by [buying one of our paid products](https://spatie.be/open-source/support-us). diff --git a/docs/upgrade-guide.md b/docs/upgrade-guide.md new file mode 100644 index 00000000..b921dee5 --- /dev/null +++ b/docs/upgrade-guide.md @@ -0,0 +1,39 @@ +--- +title: Upgrade guide +weight: 2 +--- + +In the `4.x` version, we have introduced the contract concept to the Tenant so that any model could implement the interface. + +The first step to reach our goal is upgrading our package version. + +```sh +composer require spatie/laravel-multitenancy:^4.0 +``` + +### Removed `UsesTenantModel` trait +Remove any reference to our old trait `Spatie\Models\Concerns\UsesTenantModel`, because now the right `Tenant` instance can be resolved using `app(IsTenant::class)`. + +### Tenant finder +If you are using the default finder included in the package, no changes are required by your side. However, when you are using a custom finder, you need to change the returned value in `findForRequest` method to `?IsTenant`. Example: + +```php +use Illuminate\Http\Request; +use Spatie\Multitenancy\Contracts\IsTenant; + +class YourCustomTenantFinder extends TenantFinder +{ + public function findForRequest(Request $request): ?IsTenant + { + // ... + } +} +``` + +### Custom tasks +As has already been pointed out for the finder, the same change is required for any task because our `SwitchTenantTask` interface now is: +```php +public function makeCurrent(IsTenant $tenant): void; +``` + +So, it requires replacing the method parameter from `Tenant $tenant` to `IsTenant $tenant.` From ad8b24c38c6a785352635f3d356ade2a876bb595 Mon Sep 17 00:00:00 2001 From: Freek Van der Herten Date: Thu, 18 Jul 2024 17:06:31 +0200 Subject: [PATCH 12/17] Update upgrade-guide.md --- docs/upgrade-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/upgrade-guide.md b/docs/upgrade-guide.md index b921dee5..383b479c 100644 --- a/docs/upgrade-guide.md +++ b/docs/upgrade-guide.md @@ -7,7 +7,7 @@ In the `4.x` version, we have introduced the contract concept to the Tenant so t The first step to reach our goal is upgrading our package version. -```sh +```bash composer require spatie/laravel-multitenancy:^4.0 ``` From a699b5827cf7ad95bbf6221b9f6c505adf3ab5e6 Mon Sep 17 00:00:00 2001 From: Luca Longo Date: Fri, 19 Jul 2024 12:11:59 +0200 Subject: [PATCH 13/17] Update working-with-the-current-tenant.md --- .../working-with-the-current-tenant.md | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/docs/basic-usage/working-with-the-current-tenant.md b/docs/basic-usage/working-with-the-current-tenant.md index baed5a51..db0a2eff 100644 --- a/docs/basic-usage/working-with-the-current-tenant.md +++ b/docs/basic-usage/working-with-the-current-tenant.md @@ -3,14 +3,18 @@ title: Working with the current tenant weight: 3 --- -There are several methods available to get, set and clear the current tenant. +There are several methods available to get, set and clear the current tenant. All methods are available using the Tenant model directly, or through the Laravel Service Container `app(IsTenant::class)`. ### Finding the current tenant You can find the current tenant like this: ```php -Spatie\Multitenancy\Models\Tenant::current(); // returns the current tenant, or if no tenant is current, `null` +// Model +Tenant::current(); // returns the current tenant, or if no tenant is current, `null` + +// Service Container +app(IsTenant::class)::current(); // returns the current tenant, or if no tenant is current, `null` ``` A current tenant will also be bound in the container using the `currentTenant` key. @@ -24,7 +28,11 @@ app('currentTenant'); // returns the current tenant, or if no tenant is current, You can check if there is tenant set as the current one: ```php -Tenant::checkCurrent() // returns `true` or `false` +// Model +Tenant::checkCurrent(); // returns `true` or `false` + +// Service Container +app(IsTenant::class)::checkCurrent(); // returns `true` or `false` ``` ### Manually setting the current tenant @@ -42,9 +50,13 @@ When a tenant is made the current one, the package will run the `makeCurrent` me You can forget the current tenant: ```php +// Model Tenant::forgetCurrent(); - Tenant::current() // return null; + +// Service Container +app(IsTenant::class)::forgetCurrent(); +app(IsTenant::class)::current(); // return null ``` If there was no tenant current when calling `forgetCurrent`, the function will do nothing. From dc2778631a0cc79e13e1a0fda78f45d64dbc0f2b Mon Sep 17 00:00:00 2001 From: Luca Longo Date: Mon, 22 Jul 2024 16:43:46 +0200 Subject: [PATCH 14/17] Implements Context --- config/multitenancy.php | 19 +++----- src/Actions/ForgetCurrentTenantAction.php | 8 +++- src/Actions/MakeQueueTenantAwareAction.php | 45 ++++--------------- src/Concerns/BindAsCurrentTenant.php | 6 +++ src/Concerns/UsesMultitenancyConfig.php | 5 +++ src/MultitenancyServiceProvider.php | 11 ++++- tests/Feature/Models/TenantTest.php | 14 ++++-- .../QueueIsTenantAwareByDefaultTest.php | 8 ++-- .../TenantAwareJobsByConfigTest.php | 8 ++-- .../TestClasses/MailableTenantAware.php | 2 +- .../TenantAwareJobs/TestClasses/TestJob.php | 5 ++- 11 files changed, 65 insertions(+), 66 deletions(-) diff --git a/config/multitenancy.php b/config/multitenancy.php index 94e06ed2..016fe263 100644 --- a/config/multitenancy.php +++ b/config/multitenancy.php @@ -66,6 +66,11 @@ */ 'landlord_database_connection_name' => null, + /* + * This key will be used to associate the current tenant in the context + */ + 'current_tenant_context_key' => 'tenantId', + /* * This key will be used to bind the current tenant in the container. */ @@ -88,20 +93,6 @@ 'migrate_tenant' => MigrateTenantAction::class, ], - /* - * You can customize the way in which the package resolves the queueable to a job. - * - * For example, using the package laravel-actions (by Loris Leiva), you can - * resolve JobDecorator to getAction() like so: JobDecorator::class => 'getAction' - */ - 'queueable_to_job' => [ - SendQueuedMailable::class => 'mailable', - SendQueuedNotifications::class => 'notification', - CallQueuedClosure::class => 'closure', - CallQueuedListener::class => 'class', - BroadcastEvent::class => 'event', - ], - /* * Jobs tenant aware even if these don't implement the TenantAware interface. */ diff --git a/src/Actions/ForgetCurrentTenantAction.php b/src/Actions/ForgetCurrentTenantAction.php index a3ff21c9..b1cb12f2 100644 --- a/src/Actions/ForgetCurrentTenantAction.php +++ b/src/Actions/ForgetCurrentTenantAction.php @@ -2,6 +2,8 @@ namespace Spatie\Multitenancy\Actions; +use Illuminate\Support\Facades\Context; +use Spatie\Multitenancy\Concerns\UsesMultitenancyConfig; use Spatie\Multitenancy\Contracts\IsTenant; use Spatie\Multitenancy\Events\ForgettingCurrentTenantEvent; use Spatie\Multitenancy\Events\ForgotCurrentTenantEvent; @@ -10,6 +12,8 @@ class ForgetCurrentTenantAction { + use UsesMultitenancyConfig; + public function __construct( protected TasksCollection $tasksCollection ) { @@ -35,8 +39,8 @@ protected function performTaskToForgetCurrentTenant(): static protected function clearBoundCurrentTenant(): void { - $containerKey = config('multitenancy.current_tenant_container_key'); + app()->forgetInstance($this->currentTenantContainerKey()); - app()->forgetInstance($containerKey); + Context::forget($this->currentTenantContextKey()); } } diff --git a/src/Actions/MakeQueueTenantAwareAction.php b/src/Actions/MakeQueueTenantAwareAction.php index bc4ebce3..1d222296 100644 --- a/src/Actions/MakeQueueTenantAwareAction.php +++ b/src/Actions/MakeQueueTenantAwareAction.php @@ -4,8 +4,9 @@ use Illuminate\Queue\Events\JobProcessing; use Illuminate\Queue\Events\JobRetryRequested; -use Illuminate\Support\Arr; +use Illuminate\Support\Facades\Context; use Spatie\Multitenancy\Concerns\BindAsCurrentTenant; +use Spatie\Multitenancy\Concerns\UsesMultitenancyConfig; use Spatie\Multitenancy\Contracts\IsTenant; use Spatie\Multitenancy\Exceptions\CurrentTenantCouldNotBeDeterminedInTenantAwareJob; use Spatie\Multitenancy\Jobs\NotTenantAware; @@ -14,30 +15,15 @@ class MakeQueueTenantAwareAction { use BindAsCurrentTenant; + use UsesMultitenancyConfig; public function execute(): void { $this - ->listenForJobsBeingQueued() ->listenForJobsBeingProcessed() ->listenForJobsRetryRequested(); } - protected function listenForJobsBeingQueued(): static - { - app('queue')->createPayloadUsing(function ($connectionName, $queue, $payload) { - $queueable = $payload['data']['command']; - - if (! $this->isTenantAware($queueable)) { - return []; - } - - return ['tenantId' => app(IsTenant::class)::current()?->getKey()]; - }); - - return $this; - } - protected function listenForJobsBeingProcessed(): static { app('events')->listen(JobProcessing::class, function (JobProcessing $event) { @@ -56,9 +42,11 @@ protected function listenForJobsRetryRequested(): static return $this; } - protected function isTenantAware(object $queueable): bool + protected function isTenantAware(JobProcessing|JobRetryRequested $event): bool { - $reflection = new \ReflectionClass($this->getJobFromQueueable($queueable)); + $jobName = $this->getEventPayload($event)['data']['commandName']; + + $reflection = new \ReflectionClass($jobName); if ($reflection->implementsInterface(TenantAware::class)) { return true; @@ -90,7 +78,7 @@ protected function getEventPayload($event): ?array protected function findTenant(JobProcessing|JobRetryRequested $event): IsTenant { - $tenantId = $this->getEventPayload($event)['tenantId'] ?? null; + $tenantId = Context::get($this->currentTenantContextKey()); if (! $tenantId) { $event->job->delete(); @@ -107,24 +95,9 @@ protected function findTenant(JobProcessing|JobRetryRequested $event): IsTenant return $tenant; } - protected function getJobFromQueueable(object $queueable) - { - $job = Arr::get(config('multitenancy.queueable_to_job'), $queueable::class); - - if (! $job) { - return $queueable; - } - - if (method_exists($queueable, $job)) { - return $queueable->{$job}(); - } - - return $queueable->$job; - } - protected function bindOrForgetCurrentTenant(JobProcessing|JobRetryRequested $event): void { - if (array_key_exists('tenantId', $this->getEventPayload($event))) { + if ($this->isTenantAware($event)) { $this->bindAsCurrentTenant($this->findTenant($event)->makeCurrent()); return; diff --git a/src/Concerns/BindAsCurrentTenant.php b/src/Concerns/BindAsCurrentTenant.php index 9ef18d4a..4d919d9c 100644 --- a/src/Concerns/BindAsCurrentTenant.php +++ b/src/Concerns/BindAsCurrentTenant.php @@ -2,18 +2,24 @@ namespace Spatie\Multitenancy\Concerns; +use Illuminate\Support\Facades\Context; use Spatie\Multitenancy\Contracts\IsTenant; trait BindAsCurrentTenant { protected function bindAsCurrentTenant(IsTenant $tenant): static { + $contextKey = config('multitenancy.current_tenant_context_key'); $containerKey = config('multitenancy.current_tenant_container_key'); + Context::forget($contextKey); + app()->forgetInstance($containerKey); app()->instance($containerKey, $tenant); + Context::add($contextKey, $tenant->getKey()); + return $this; } } diff --git a/src/Concerns/UsesMultitenancyConfig.php b/src/Concerns/UsesMultitenancyConfig.php index 1d3c4498..e197121e 100644 --- a/src/Concerns/UsesMultitenancyConfig.php +++ b/src/Concerns/UsesMultitenancyConfig.php @@ -17,6 +17,11 @@ public function landlordDatabaseConnectionName(): ?string return config('multitenancy.landlord_database_connection_name') ?? config('database.default'); } + public function currentTenantContextKey(): string + { + return config('multitenancy.current_tenant_context_key'); + } + public function currentTenantContainerKey(): string { return config('multitenancy.current_tenant_container_key'); diff --git a/src/MultitenancyServiceProvider.php b/src/MultitenancyServiceProvider.php index 0606d043..5f94e80c 100644 --- a/src/MultitenancyServiceProvider.php +++ b/src/MultitenancyServiceProvider.php @@ -2,6 +2,8 @@ namespace Spatie\Multitenancy; +use Illuminate\Log\Context\Repository; +use Illuminate\Support\Facades\Context; use Illuminate\Support\Facades\Event; use Laravel\Octane\Events\RequestReceived as OctaneRequestReceived; use Laravel\Octane\Events\RequestTerminated as OctaneRequestTerminated; @@ -30,13 +32,20 @@ public function packageBooted(): void $this->app->bind(Multitenancy::class, fn ($app) => new Multitenancy($app)); + $this->detectsLaravelOctane(); + } + + protected function detectsLaravelOctane(): static + { if (! isset($_SERVER['LARAVEL_OCTANE'])) { app(Multitenancy::class)->start(); - return; + return $this; } Event::listen(fn (OctaneRequestReceived $requestReceived) => app(Multitenancy::class)->start()); Event::listen(fn (OctaneRequestTerminated $requestTerminated) => app(Multitenancy::class)->end()); + + return $this; } } diff --git a/tests/Feature/Models/TenantTest.php b/tests/Feature/Models/TenantTest.php index 97a9a2ab..6d550a82 100644 --- a/tests/Feature/Models/TenantTest.php +++ b/tests/Feature/Models/TenantTest.php @@ -1,5 +1,6 @@ tenant->makeCurrent(); - expect(Tenant::current()->id)->toEqual($this->tenant->id); - expect(app()->has($containerKey))->toBeTrue(); + + expect(Tenant::current()->id)->toEqual($this->tenant->id) + ->and(app()->has($containerKey))->toBeTrue() + ->and(Context::get($contextKey))->toEqual($this->tenant->id); Tenant::forgetCurrent(); - expect(Tenant::current())->toBeNull(); - expect(app())->has($containerKey)->toBeFalse(); + + expect(Tenant::current())->toBeNull() + ->and(app())->has($containerKey)->toBeFalse() + ->and(Context::get($contextKey))->toBeNull(); }); it('can check if a current tenant has been set', function () { diff --git a/tests/Feature/TenantAwareJobs/QueueIsTenantAwareByDefaultTest.php b/tests/Feature/TenantAwareJobs/QueueIsTenantAwareByDefaultTest.php index 309dbe5d..7b92ee06 100644 --- a/tests/Feature/TenantAwareJobs/QueueIsTenantAwareByDefaultTest.php +++ b/tests/Feature/TenantAwareJobs/QueueIsTenantAwareByDefaultTest.php @@ -32,7 +32,9 @@ $this->artisan('queue:work --once')->assertExitCode(0); $currentTenantIdInJob = $this->valuestore->get('tenantId'); - expect($this->tenant->id)->toEqual($currentTenantIdInJob); + + expect($this->valuestore->get('tenantIdInContext'))->toBe($this->tenant->getKey()) + ->and($this->tenant->id)->toEqual($currentTenantIdInJob); }); it('will inject the right tenant even when the current tenant switches', function () { @@ -69,7 +71,7 @@ $this->artisan('queue:work --once')->assertExitCode(0); - $currentTenantIdInJob = $this->valuestore->get('tenantIdInPayload'); + $currentTenantIdInJob = $this->valuestore->get('tenantId'); expect($currentTenantIdInJob)->toBeNull(); }); @@ -97,6 +99,6 @@ $this->artisan('queue:work --once')->assertExitCode(0); - $currentTenantIdInJob = $this->valuestore->get('tenantIdInPayload'); + $currentTenantIdInJob = $this->valuestore->get('tenantId'); expect($currentTenantIdInJob)->toBeNull(); }); diff --git a/tests/Feature/TenantAwareJobs/TenantAwareJobsByConfigTest.php b/tests/Feature/TenantAwareJobs/TenantAwareJobsByConfigTest.php index 50c81ce3..2d5b110b 100644 --- a/tests/Feature/TenantAwareJobs/TenantAwareJobsByConfigTest.php +++ b/tests/Feature/TenantAwareJobs/TenantAwareJobsByConfigTest.php @@ -21,8 +21,8 @@ app(Dispatcher::class)->dispatch(new TestJob($this->valuestore)); - expect($this->valuestore->has('tenantIdInPayload'))->toBeTrue() - ->and($this->valuestore->get('tenantIdInPayload'))->not->toBeNull(); + expect($this->valuestore->has('tenantIdInContext'))->toBeTrue() + ->and($this->valuestore->get('tenantIdInContext'))->not->toBeNull(); }); it('fails with jobs in not tenant aware jobs list', function () { @@ -33,6 +33,6 @@ app(Dispatcher::class)->dispatch(new TestJob($this->valuestore)); expect($this->valuestore->get('tenantId'))->toBeNull() - ->and($this->valuestore->has('tenantIdInPayload'))->toBeTrue() - ->and($this->valuestore->get('tenantIdInPayload'))->toBeNull(); + ->and($this->valuestore->get('tenantName'))->toBeNull() + ->and($this->valuestore->has('tenantIdInContext'))->toBeTrue(); }); diff --git a/tests/Feature/TenantAwareJobs/TestClasses/MailableTenantAware.php b/tests/Feature/TenantAwareJobs/TestClasses/MailableTenantAware.php index e82a4383..d009d7b9 100644 --- a/tests/Feature/TenantAwareJobs/TestClasses/MailableTenantAware.php +++ b/tests/Feature/TenantAwareJobs/TestClasses/MailableTenantAware.php @@ -8,7 +8,7 @@ class MailableTenantAware extends Mailable implements ShouldQueue, TenantAware { - public function build() + public function build(): Mailable { return $this->view('mailable'); } diff --git a/tests/Feature/TenantAwareJobs/TestClasses/TestJob.php b/tests/Feature/TenantAwareJobs/TestClasses/TestJob.php index 9630bc50..8fb9431d 100644 --- a/tests/Feature/TenantAwareJobs/TestClasses/TestJob.php +++ b/tests/Feature/TenantAwareJobs/TestClasses/TestJob.php @@ -5,6 +5,8 @@ use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; +use Illuminate\Support\Facades\Context; +use Spatie\Multitenancy\Concerns\UsesMultitenancyConfig; use Spatie\Multitenancy\Models\Tenant; use Spatie\Valuestore\Valuestore; @@ -12,6 +14,7 @@ class TestJob implements ShouldQueue { use InteractsWithQueue; use Dispatchable; + use UsesMultitenancyConfig; public Valuestore $valuestore; @@ -22,7 +25,7 @@ public function __construct(Valuestore $valuestore) public function handle() { - $this->valuestore->put('tenantIdInPayload', $this->job?->payload()['tenantId'] ?? null); + $this->valuestore->put('tenantIdInContext', Context::get($this->currentTenantContextKey())); $this->valuestore->put('tenantId', Tenant::current()?->id); $this->valuestore->put('tenantName', Tenant::current()?->name); } From 9d7a046406277a28649ecb2db5defb7d55b3d659 Mon Sep 17 00:00:00 2001 From: masterix21 Date: Mon, 22 Jul 2024 14:44:03 +0000 Subject: [PATCH 15/17] Fix styling --- src/MultitenancyServiceProvider.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/MultitenancyServiceProvider.php b/src/MultitenancyServiceProvider.php index 5f94e80c..b28c57a6 100644 --- a/src/MultitenancyServiceProvider.php +++ b/src/MultitenancyServiceProvider.php @@ -2,8 +2,6 @@ namespace Spatie\Multitenancy; -use Illuminate\Log\Context\Repository; -use Illuminate\Support\Facades\Context; use Illuminate\Support\Facades\Event; use Laravel\Octane\Events\RequestReceived as OctaneRequestReceived; use Laravel\Octane\Events\RequestTerminated as OctaneRequestTerminated; From 86e90a6ffc85cd09bd358f2250128d28e139fc1c Mon Sep 17 00:00:00 2001 From: Luca Longo Date: Mon, 22 Jul 2024 16:45:55 +0200 Subject: [PATCH 16/17] Update base-installation.md --- docs/installation/base-installation.md | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/docs/installation/base-installation.md b/docs/installation/base-installation.md index 710c6a57..e0b282ce 100644 --- a/docs/installation/base-installation.md +++ b/docs/installation/base-installation.md @@ -88,6 +88,11 @@ return [ */ 'landlord_database_connection_name' => null, + /* + * This key will be used to associate the current tenant in the context + */ + 'current_tenant_context_key' => 'tenantId', + /* * This key will be used to bind the current tenant in the container. */ @@ -110,20 +115,6 @@ return [ 'migrate_tenant' => MigrateTenantAction::class, ], - /* - * You can customize the way in which the package resolves the queueable to a job. - * - * For example, using the package laravel-actions (by Loris Leiva), you can - * resolve JobDecorator to getAction() like so: JobDecorator::class => 'getAction' - */ - 'queueable_to_job' => [ - SendQueuedMailable::class => 'mailable', - SendQueuedNotifications::class => 'notification', - CallQueuedClosure::class => 'closure', - CallQueuedListener::class => 'class', - BroadcastEvent::class => 'event', - ], - /* * Jobs tenant aware even if these don't implement the TenantAware interface. */ From 5ac00aa30e185b393ef7897dfdc65991e8b943eb Mon Sep 17 00:00:00 2001 From: Luca Longo Date: Mon, 22 Jul 2024 16:58:24 +0200 Subject: [PATCH 17/17] Update multitenancy.php --- config/multitenancy.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/config/multitenancy.php b/config/multitenancy.php index 016fe263..4bdd558b 100644 --- a/config/multitenancy.php +++ b/config/multitenancy.php @@ -1,10 +1,5 @@