How it works
Our package is entirely event-based. Out of the box, this is what would happen in a request if you were using domain identification with multi-database tenancy1:
- A request comes in, for a route defined in
routes/tenant.php - One of the first middleware in the route middleware stack is
InitializeTenancyByDomain InitializeTenancyByDomaintakes the domain from the request:$request->getHost()- It checks if that domain belongs to any tenant
- If it doesn’t, a 404 is returned2. If it does:
tenancy()->initialize($tenant)is calledtenancy()->initialize()sets the provided tenant as the current tenant (tenancy()->tenant) and fires theTenancyInitializedeventBootstrapTenancylistens toTenancyInitialized(these listeners are configured in yourTenancyServiceProvider)BootstrapTenancycalls all of the bootstrappers configured inconfig/tenancy.php- The bootstrappers scope your application to that tenant — for instance the
DatabaseTenancyBootstrapperwould switch the default database connection to the tenant’s database - The route action — the controller method — is executed, fully in the tenant context
This can be simplified into two parts:
- Tenant identification: identifying a tenant from the request in the middleware
- Tenancy initialization: calling
tenancy()->initialize($tenant)after we have a tenant instance. This sets the tenant as the current tenant and fires theTenancyInitializedevent, which theBootstrapTenancyclass listens to
Tenant identification is always related to routing and as such takes place in middleware.
Tenancy initialization can be done anywhere: you can run php artisan tinker, type in tenancy()->initialize(Tenant::first()), and you’d be in that tenant’s context.
Footnotes
Section titled “Footnotes”-
This is, of course, configurable. You could be using path segments or request headers (among other things) to identify tenants, and you might not be using multi-database tenancy. This is just the default common setup that makes explaining how the package works easy. ↩
-
Alternatively, instead of a 404, the request could simply proceed without tenancy initialization — in the central context. That’s what the Universal Routes feature does. ↩