Configuration

Sprout has a handful of configuration options, and while they are all set to sensible defaults, it's worth understanding what each of them does.

Introduction

Sprout comes with two config files, sprout.php and multitenancy.php. You can publish these config files using Laravel's vendor:publish command, like so:

1php artisan vendor:publish --provider="Sprout\SproutServiceProvider"

The config is also tagged as config and sprout-config, if you prefer to publish that way.

Multitenancy Config

The first of the two config files is multitenancy.php which is where you configure your multitenancy implementation. If you've ever had to work with Laravel's auth.php config file, some of this may be familiar to you.

Multitenancy Defaults

The first option within the multitenancy config is defaults, which functions identically to auth.defaults.

1'defaults' => [
2 'tenancy' => 'tenants',
3 'provider' => 'tenants',
4 'resolver' => 'subdomain',
5],

This option allows you to set the default tenancy, provider and resolver that will be used in several places if one wasn't explicitly provided.

Tenancies

The next open is tenancies, which lets you configure the different tenancies that your application has. For most applications, you'll only have one type of tenant, so you'll only have one tenancy.

1'tenancies' => [
2 'tenants' => [
3 'provider' => 'tenants',
4 'options' => [
5 TenancyOptions::hydrateTenantRelation(),
6 TenancyOptions::throwIfNotRelated(),
7 ],
8 ],
9],

Every tenancy can have a provider, and an array of options. Both of these config options are entirely optional.

Tenancy Provider

The provider option within a tenancy config will tell Sprout which tenancy provider to use. The value should match the name of a tenancy provider configured in the next section of the config.

If the value is null, or the entry is missing entirely, the default tenancy provider defined in multitenancy.defaults.provider will be used.

Tenancy Options

The options option within a tenancy config allows you finer control over the behaviour of a particular tenancy. Options are provided by the Sprout\TenancyOptions class, which currently provides two options.

  • TenancyOptions::hydrateTenantRelation() — Tells Sprout to automatically hydrate the tenant relation of a retrieved model with the current tenant.
  • TenancyOptions::throwIfNotRelated() — Tells Sprout to throw an exception if a model retrieved from the database, or attempting to be created doesn't relate to the current tenant.

Tenancy Providers

Following on from tenancies, the next option within the multitenancy config file is providers, which allows you to configure separate tenancy providers. Tenancy providers are

1'providers' => [
2 'tenants' => [
3 'driver' => 'eloquent',
4 'model' => \Sprout\Database\Eloquent\Tenant::class,
5 ],
6 // 'backup' => [
7 // 'driver' => 'database',
8 // 'table' => 'tenants',
9 // ],
10],

A tenant provider requires a driver, with all other options being dictated by the driver you choose. The following drivers are supported out of the box:

Identity Resolvers

Finally, we have the resolvers option, which is where you can configure the different identity resolvers that you require in your application. Identity resolvers are classes responsible for location a tenants' identifier within a request, and they are not tied to a specific provider or tenancy.

1'resolvers' => [
2 'subdomain' => [
3 'driver' => 'subdomain',
4 'domain' => env('TENANTED_DOMAIN'),
5 'pattern' => '.*',
6 ],
7 'header' => [
8 'driver' => 'header',
9 'header' => '{Tenancy}-Identifier',
10 ],
11 'path' => [
12 'driver' => 'path',
13 'segment' => 1,
14 ],
15 'cookie' => [
16 'driver' => 'cookie',
17 'cookie' => '{Tenancy}-Identifier',
18 ],
19 'session' => [
20 'driver' => 'session',
21 'session' => 'multitenancy.{tenancy}',
22 ],
23],

An identity resolver requires a driver, with all other options being dictated by the driver you pick. The following drivers are supported out of the box:

It should be noted that the default names are there for simplicity, and you may change them to whatever you see fit. It is also recommended that you remove any you don't plan to use.

Sprout Config

The second of the two config files is sprout.php which contains configuration specific to the general running of Sprout itself. This file has three separate config options.

Enabled Hooks

The hooks option within the Sprout config controls where in the lifecycle of the Laravel application, Sprout should attempt to identity a tenant.

1'hooks' => [
2 // \Sprout\Support\ResolutionHook::Booting,
3 \Sprout\Support\ResolutionHook::Routing,
4 \Sprout\Support\ResolutionHook::Middleware,
5],

The values are provided by the enum Sprout\Support\ResolutionHook, and the following are available:

ResolutionHook::Routing

This hook will tell Sprout to attempt to identify tenants when receiving a Illuminate\Routing\Events\RouteMatched event. This is the recommended location for tenant identification, and will suffice for most use cases.

ResolutionHook::Middleware

This hook will tell Sprout to attempt to identify tenants within the middleware phase of routing. It is recommended that you keep this hook enabled as it allows for fallback identification should the routing approach fail for some reason.

ResolutionHook::Booting

This hook will tell Sprout to attempt to identify tenants during the booting of the framework, more specifically, in the boot phase of a service provider.

This hook is only present for future compatibility, and is not currently supported.

Bootstrappers

The bootstrappers option within the Sprout config is a priority ordered list of event listeners that should run when a tenant becomes the current tenant.

1'bootstrappers' => [
2 // Set the current tenant within the Laravel context
3 \Sprout\Listeners\SetCurrentTenantContext::class,
4 // Calls the setup method on the current identity resolver
5 \Sprout\Listeners\PerformIdentityResolverSetup::class,
6 // Performs any clean-up from the previous tenancy
7 \Sprout\Listeners\CleanupServiceOverrides::class,
8 // Sets up service overrides for the current tenancy
9 \Sprout\Listeners\SetupServiceOverrides::class,
10],

These listeners are all for the Sprout\Events\CurrentTenantChanged event, and are registered during the boot phase of the Sprout service provider. The list exists specifically so that you can control the default behaviour of bootstrapping a tenancy.

Since these are simply listeners to a Sprout event, you can create your own with the following command:

1php artisan make:listener MyTenancyBootstrapper --event="Sprout\Events\CurrentTenantChanged"

If you wish to create your own bootstrapper, you only need to add it to this list if the order in which it is fired is important.

SetCurrentTenantContext

The SetCurrentTenantContext bootstrapper ensures that the current tenant for all active tenancies has their key present within Laravel's context. The context key is sprout.tenants, which contains an array of tenancy => key mappings, where tenancy is the name of the tenancy configured in multitenancy.tenancies, and key is the tenant's key.

PerformIdentityResolverSetup

Some identity resolvers have actions that should be performed when a tenancy is bootstrapped off the back of them. For example, parameter-based identity resolvers will set default values for the route parameters, so you don't have to manually provide them when generating a route URL.

CleanupServiceOverrides

Since Sprout allows you to switch the current tenant during a request, it's entirely possible that a single request bootstraps two tenants tenancies. Because of this, Sprouts service overrides can have clean-up actions to prevent tenant configuration, services and set-ups from leaking.

This bootstrapper should always come before the SetupServiceOverrides, because some of Laravel's services will use old configured instances if they're still around.

SetupServiceOverrides

This particular bootstrapper is responsible for allowing service overrides to perform their various setup actions. Not all overrides will have setup actions, but if they do, what they are will depend entirely on the service they're overriding.

Services

The final option in the Sprout config is services, which contains the service overrides that should be enabled for the application.

1'services' => [
2 // This will override the storage by introducing a 'sprout' driver
3 // that wraps any other storage drive in a tenant resource subdirectory.
4 \Sprout\Overrides\StorageOverride::class,
5 // This will hydrate tenants when running jobs, based on the current
6 // context.
7 \Sprout\Overrides\JobOverride::class,
8 // This will override the cache by introducing a 'sprout' driver
9 // that adds a prefix to cache stores for the current tenant.
10 \Sprout\Overrides\CacheOverride::class,
11 // This is a simple override that removes all currently resolved
12 // guards to prevent user auth leaking.
13 \Sprout\Overrides\AuthOverride::class,
14 // This will override the cookie settings so that all created cookies
15 // are specific to the tenant.
16 \Sprout\Overrides\CookieOverride::class,
17 // This will override the session by introducing a 'sprout' driver
18 // that wraps any other session store.
19 \Sprout\Overrides\SessionOverride::class,
20],

The order that the service overrides appear within this list is the order that they will be added in.

By default, all the available service overrides that Sprout ships with are enabled. You can find out more about the individual service overrides from within their documentation.

The following are available as part of Sprout: