Skip to content

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:

  1. A request comes in, for a route defined in routes/tenant.php
  2. One of the first middleware in the route middleware stack is InitializeTenancyByDomain
  3. InitializeTenancyByDomain takes the domain from the request: $request->getHost()
  4. It checks if that domain belongs to any tenant
  5. If it doesn’t, a 404 is returned2. If it does:
  6. tenancy()->initialize($tenant) is called
  7. tenancy()->initialize() sets the provided tenant as the current tenant (tenancy()->tenant) and fires the TenancyInitialized event
  8. BootstrapTenancy listens to TenancyInitialized (these listeners are configured in your TenancyServiceProvider)
  9. BootstrapTenancy calls all of the bootstrappers configured in config/tenancy.php
  10. The bootstrappers scope your application to that tenant — for instance the DatabaseTenancyBootstrapper would switch the default database connection to the tenant’s database
  11. The route action — the controller method — is executed, fully in the tenant context

This can be simplified into two parts:

  1. Tenant identification: identifying a tenant from the request in the middleware
  2. Tenancy initialization: calling tenancy()->initialize($tenant) after we have a tenant instance. This sets the tenant as the current tenant and fires the TenancyInitialized event, which the BootstrapTenancy class 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.

  1. 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.

  2. 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.