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 resolved12 // guards to prevent user auth leaking.13 \Sprout\Overrides\AuthOverride::class,14 // This will override the cookie settings so that all created cookies15 // are specific to the tenant.16 \Sprout\Overrides\CookieOverride::class,17 // This will override the session by introducing a 'sprout' driver18 // 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: