UrlGeneratorBootstrapper
The UrlGeneratorBootstrapper overrides the default UrlGenerator with our own TenancyUrlGenerator
which supports context-aware route generation. In other words, it makes generating URLs easier
in the tenant context, especially with path identification or third-party package integrations.
UrlGeneratorBootstrapper class
Section titled “UrlGeneratorBootstrapper class”If this bootstrapper is enabled, it will override the default UrlGenerator with TenancyUrlGenerator
as mentioned above. In addition to that, it has one configurable
static property:
UrlGeneratorBootstrapper::$addTenantParameterToDefaults = true;If this property is set to true, the URL generator override will add:
'tenant' => tenant()->getTenantKey(),to URL::defaults(). That is a URL generator feature which sets default parameter values, in
other words if you have a route with a {tenant} parameter and you set a default value for
the tenant parameter, you can generate the route as route('foo') instead of
route('foo', ['tenant' => tenant('id')]). This is in line with how the rest of the package
tries to minimize code changes across application code (and especially useful with third-party
package integrations as mentioned above).
Note that the default value isn’t literally the above. Instead, it follows this config:
'resolvers' => [ // ... Resolvers\PathTenantResolver::class => [ 'tenant_parameter_name' => 'tenant', 'tenant_model_column' => null, // null = tenant key 'tenant_route_name_prefix' => 'tenant.', 'allowed_extra_model_columns' => [], // used with binding route fields
'cache' => false, 'cache_ttl' => 3600, // seconds 'cache_store' => null, // null = default ], // ...In other words, with this config:
'tenant_parameter_name' => 'team','tenant_model_column' => 'slug',The parameter would be set as:
'team' => tenant()->slug,In addition to setting a default value for the tenant_parameter_name, the bootstrapper also
sets defaults for all extra model columns whitelisted in allowed_extra_model_columns, also in
the config above. For instance this config:
'tenant_parameter_name' => 'team','tenant_model_column' => null,'allowed_extra_model_columns' => ['slug'],Would set the following default values:
'team' => tenant()->getTenantKey(),'team:slug' => tenant()->slug,Which would also support routes with binding fields, i.e.:
Route::get('/{team:slug}/foo', ...)->name('tenant.foo');
// these would work the same:route('tenant.foo');route('tenant.foo', ['team' => tenant()->slug]);TenancyUrlGenerator class
Section titled “TenancyUrlGenerator class”The TenancyUrlGenerator class provides further configuration options:
TenancyUrlGenerator:$prefixRouteNames = false;The $prefixRouteNames static property tells
the URL generator override whether route names should be prefixed with tenant. (the actual prefix
name comes from PathTenantResolver::tenantRouteNamePrefix() — see the config discussed above).
In other words, if you are in the tenant context, route generation works like this:
route('foo'); // becomes route('tenant.foo')route('tenant.foo'); // no change as the route name already starts with the tenant prefixTenancyUrlGenerator:$passTenantParameterToRoutes = false;The $passTenantParameterToRoutes static property tells the URL generator override whether the
tenant parameter (again name comes from PathTenantResolver::tenantParameterName()) should be
passed to the route parameters. This is typically not needed if URL defaults are already used, but
you may prefer that the parameter is passed directly instead of depending on URL defaults, if URL
defaults don’t work for your use case for some reason.
TenancyUrlGenerator:$passQueryParameter = false;The $passQueryParameter static property tells the URL generator override to pass a query
parameter instead of the tenant parameter mentioned above to the routes. This option requires
that $passTenantParameterToRoutes is enabled. This setting changes the passed parameter
to instead be RequestDataTenantResolver::queryParameterName(), with a value of
RequestDataTenantResolver::payloadValue(tenant()), instead of
PathTenantResolver::tenantParameterName(). The use case is query parameter identification with
the InitializeTenancyByRequestData middleware.
See the relevant configuration:
Resolvers\RequestDataTenantResolver::class => [ // Set any of these to null to disable that method of identification 'header' => 'X-Tenant', 'cookie' => 'tenant', 'query_parameter' => 'tenant',
'tenant_model_column' => null, // null = tenant key
'cache' => false, 'cache_ttl' => 3600, // seconds 'cache_store' => null, // null = default],You may also want to take a look at the methods mentioned above directly.
TenancyUrlGenerator::$overrides = [];The $overrides static property tells the URL generator override to replace some routes with other
routes in the tenant context. The typical use case is that you’d want to keep $prefixRouteNames
disabled, and instead only pass a small set of routes to be replaced to this array. This can be
helpful if you only have a handful of routes that have a tenant variant, that existing (including
third-party package) code, should use instead of the existing central route calls, but you also
have many central route calls that you don’t want to have to add the bypass parameter to.
TenancyUrlGenerator::$bypassParameter = 'central';The $bypassParameter static property lets you customize the name of the bypass parameter,
i.e. the parameter that can be used to “escape” the tenant scoping and generate a route as if you
were currently in the central context. In other words, overrides are ignored, route names are not
prefixed, and the tenant parameter or query parameter is not passed.
Example with path identification
Section titled “Example with path identification”It’s common for path identification setups to have clones of some
central routes, often authentication routes, with shared code in the central and tenant context
that simply references e.g. route('auth.login'). You’d want this to become route('tenant.login')
in the tenant context, with the tenant parameter automatically passed in.
In such a setup, you’d enable the bootstrapper and use the following configuration:
UrlGeneratorBootstrapper::$addTenantParameterToDefaults = true;// orTenancyUrlGenerator:$passTenantParameterToRoutes = true;
TenancyUrlGenerator:$prefixRouteNames = true;It’s generally recommended to use $addTenantParameterToDefaults only — if your use case is
supported — instead of $passTenantParameterToRoutes as it’s a bit less invasive. URL defaults
are also supported by Ziggy.