Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add route cache path switcher #308

Merged
merged 5 commits into from
Nov 26, 2021
Merged

Conversation

AlexVanderbist
Copy link
Member

  • adds SwitchRouteCachePathTask + test
  • adds all included tenant switchers to config file (commented out)
  • (adds new php cs fixer cache path to gitignore

@freekmurze freekmurze merged commit e33702c into main Nov 26, 2021
@freekmurze
Copy link
Member

Flawless victory!

@freekmurze freekmurze deleted the add-route-cache-path-switcher branch November 26, 2021 13:47
@masterix21
Copy link
Collaborator

@AlexVanderbist great PR.

@masterix21
Copy link
Collaborator

masterix21 commented Nov 30, 2021

It partially works because fails with a code like so:

//
// Root path for landlord
Route::domain('landlord.test')
    ->get('/', fn () => view('welcome-landlord'));

// 
// Root path for tenant(s)
Route::middleware('tenant')
    ->domain(Tenant::current()?->host ?? 'tenant.test')
    ->get('/', fn () => view('welcome-tenant'));

The above scenario fails with the cached routes.

Do you have an idea to avoid the use of a /landlord/ path prefix?

@masterix21
Copy link
Collaborator

"However, if you're using dynamic routes, for example different routes for different tenants, you'll need to keep a separate route cache for each tenant."

Laravel route:cache uses a fresh $app object, and if you try to push new routes from a tenant task, it won't work. Do you have found another way?

@masterix21
Copy link
Collaborator

masterix21 commented Dec 1, 2021

That’s the solution to the problem.

1. Create a new task to build the tenant routes

namespace App\Tenants\Tasks;

use Illuminate\Support\Facades\Route;
use Spatie\Multitenancy\Models\Tenant;
use Spatie\Multitenancy\Tasks\SwitchTenantTask;

class SwitchRoutesTask implements SwitchTenantTask
{
    public function makeCurrent(Tenant $tenant): void
    {
        if (app()->routesAreCached()) {
            return;
        }

        Route::middleware(['api', 'tenant'])
            ->domain($tenant->host)
            ->group(base_path('routes/tenants/api.php'));

        Route::middleware(['web', 'tenant'])
            ->domain($tenant->host)
            ->group(base_path('routes/tenants/web.php'));
    }

    public function forgetCurrent(): void
    {
        // I think we should clear the router instance, but currently isn't essential for me.
    }
}

2. Update the multitenancy.php configuration like so:

'switch_tenant_tasks' => [
    // ...
    \Spatie\Multitenancy\Tasks\SwitchRouteCacheTask::class,
    \App\Tenants\Tasks\SwitchRoutesTask::class,
    // ...
],

3. Create a custom command to cache the routes

use Illuminate\Contracts\Console\Kernel as ConsoleKernelContract;
use Illuminate\Foundation\Console\RouteCacheCommand;
use Spatie\Multitenancy\Commands\Concerns\TenantAware;
use Spatie\Multitenancy\Models\Tenant;

class CacheCommand extends RouteCacheCommand
{
    use TenantAware;

    protected $signature = 'tenant:route:cache {--tenant=*}';

    protected function getFreshApplication()
    {
        $tenant = Tenant::current();

        return tap(require $this->laravel->bootstrapPath().'/app.php', function ($app) use ($tenant) {
            $app->make(ConsoleKernelContract::class)->bootstrap();

            $tenant->makeCurrent();
        });
    }
}

4. Cache your routes

php artisan tenant:route:cache

That's all.

@freekmurze / @AlexVanderbist, I think it should be helpful in the documentation. Do you think so too?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants