Skip to content

TenantConfigBootstrapper

It’s likely you will need to use tenant-specific config in your application. That config could be API keys, things like “products per page” and many other things.

You could just use the tenant model to get these values, but you may still want to use Laravel’s config() because of:

  • separation of concerns — if you just write tenancy implementation-agnostic config('shop.products_per_page'), your code will be less coupled to tenancy logic
  • default values — you may want to use tenant attributes only to override central values in your config file
  • integrating with third party packages or changing existing config within Laravel

To enable this bootstrapper, uncomment the TenantConfigBootstrapper line in the bootstrappers section of the tenancy config:

config/tenancy.php
'features' => [
// Bootstrappers\TenantConfigBootstrapper::class,
],

This bootstrapper maps tenant attributes (properties on the Tenant model, these may be custom columns or virtual columns within data) to config keys based on the $storageToConfigMap static property

For instance, if your $storageToConfigMap looked like this:

Stancl\Tenancy\Bootstrappers\TenantConfigBootstrapper::$storageToConfigMap = [
'paypal_api_key' => 'services.paypal.api_key',
];

the value of paypal_api_key in tenant model would be copied to the services.paypal.api_key config when tenancy is initialized.

Sometimes you may want to copy the value to multiple config keys. To do that, specify the config keys as an array:

Stancl\Tenancy\Bootstrappers\TenantConfigBootstrapper::$storageToConfigMap = [
'locale' => [
'app.locale',
'locales.default',
],
];

Please note that, especially when integrating with existing logic, merely changing the config may oftentimes not be enough. If some singleton reads the config value before tenancy is initialized, the config will not be read again after this bootstrapper changes the value, hence the singleton will be working with the original central value. Similarly, if a singleton (or any other type of persistent state) reads the value the first time it’s “used”, which happens in the tenant context, that may work for most things but will break if you have logic that loops over multiple tenants and initializes tenancy for each one to do some work.

This is why many of our integrations come with bootstrappers, instead of just config mappings. You are encouraged to take a look at the bootstrappers in the package codebase to get an idea of what they tend to do. In many cases, the process is essentially updating config AND purging something from a service container singleton, to force some instance to be re-resolved.