Configuration

While Sprout comes with sensible defaults meaning you'll rarely need to mess with the config, it's worth taking a look at what you can do. You never know when it'll come in handy.

Introduction

Sprout comes with a handful of configuration files, all of which have sensible defaults that should work for most applications. However, it doesn't hurt to familiarise yourself with what's available to you. Although every effort has been taken to limit the amount of configuration required, the decision to break it down into smaller chunks was made, to allow for it to be more manageable. All Sprout config follows the standard Laravel approach, so can be interacted with in the same way.

Multitenancy Configuration

The primary configuration for Sprout, and the one you're most likely to interact with, is the multitenancy.php file, which is published to config/multitenancy.php. This file allows you to customise the multitenanted aspects of your application, including:

  • The tenancies it supports
  • The different tenant providers
  • The available identity resolvers

If you're familiar enough with Laravel's other configuration, you'll notice that this file is very similar to others, particularly the auth.php file. This is because the design and structure of Sprout is quite heavily based on Laravel's auth functionality.

Sprout Configuration

The rest of the configuration provided by Sprout is published to the config/sprout directory. One of the main reasons this subdirectory is used, is so that addons can publish their own configuration files to it, making them available under the sprout. config prefix. By default, this directory contains:

  • Core Sprout configuration in core.php
  • Service override configuration in overrides.php

Configuring

Now that we've covered the different types of configuration, and where they sit on the filesystem, let's look into what you can actually configure.

Multitenancy Defaults

The first part of the multitenancy configuration is called multitenancy.defaults, which functions identically to auth.defaults, except that it's for Sprout.

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

There are lots of different ways to interact with tenancies, tenant providers, and identity resolverswithin Sprout, and this is where you can tell it, which to use by default, when none are specified. Remember that if you change the name of one of these, you'll need to update the defaults section to reflect that. Most of you will only be dealing with one tenancy, provider, and resolver, and here is where they'll be set.

Tenancies

The next option within the multitenancy configuration config, is multitenancy. tenancies, which lets you define the different tenancies that your application supports, again, similar to auth.guards.

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

Tenancies are unlike tenant providers and identity resolvers, as the default implementation doesn't require any options, and there's no support beyond a default implementation. That being said, there are three possible options that can be provided.

Tenancy Driver

The driver option of the tenancies config is purely optional. Sprout has a default tenancy implementation, which is used when this option is missing, or set to null. You can read more about custom tenancies here. This option is missing by default.

Tenancy Provider

The provider option is also entirely optional, with Sprout using the provider defined in multitenancy.defaults. provider when it's missing. If you wish to use a different provider, or manually set configure it, this value must correspond with one from the tenant providers section. By default, this will be set to the tenants provider.

Tenancy Options

The options option is also optional, and when provided should be an array. The values in this array come from the Sprout\TenancOptions class, which act as feature flags within a tenancy. Values within here are do not have to come from the TenancyOptions class, as addons and third-party packages may add their own here. By default, the tenants tenancy has three options:

  • hydrateTenantRelation - This option enables to automatic hydration of the tenant relation on a tenant child model.
  • throwIfNotRelated - This option will throw an exception if a tenant child model is not related to the current tenant.
  • allOverrides - This option will allow all service overrides to be used within the tenancy.

You can read more about tenancy options here, including which are available, and how to access them.

Tenant Providers

Next comes the multitenancy.providers section of the multitenancy configuration, which is where you can define the different tenant providers that your application supports, similar to auth.providers.

1'providers' => [
2 'tenants' => [
3 'driver' => 'eloquent',
4 'model' => \Sprout\Database\Eloquent\Tenant::class,
5 ],
6],

Tenant providers are responsible for retrieving instances of your tenant for a given request, and this is where you can define the different ones available to you. Providers only require that the driver option is provided, with all other options being dependent on the driver used.

By default, the eloquent driver is used, which requires the model option. The value provided for model is an abstract model within Sprout, but if you've followed the installation guide, you'll have already updated this. You can read more about the available tenant provider drivers here, and more about tenant providers as a concept here.

Identity Resolvers

The final part of the multitenancy configuration is the multitenancy.resolvers option, which is where you can define the different identity resolvers for your application. This feature has no corresponding component of the default auth library, as this functionality is baked into the guards.

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],

By default, Sprout comes with a configuration for every identity resolver that is supported out of the box. Most of you won't ever need to change any of this, however, you are free to do so. Just like with tenant providers, identity resolvers only require the driver option, with the rest of the options depending on the driver that you use. You can read more about available identity resolvers here, and more about identity resolvers as a concept here.

Resolution Hooks

Now we're over to the config/sprout/core.php config file, which provides some of the core sprout configuration, as the name may suggest. The first option in this file is the sprout.core.hooks option, which define the locations where Sprout will attempt to hook into a Laravel lifecycle to identity a tenant.

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

This option is a simple array of cases from the enum Sprout\Support\ResolutionHook. The presence of a hook within this will control whether certain things are booted or registered. By default, only Routing and Middleware are enabled, as Booting doesn't currently do anything. It's there for future compatibility, so it doesn't need to be enabled, although doing so won't break anything. You can read more about resolution hooks here.

Tenancy Bootstrappers

The last part of the core config is the sprout.core.bootstrappers option, which contains a collection classes that should be used to bootstrap a tenancy, once a tenant becomes the active 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 // Refresh anything that's tenant-aware
11 \Sprout\Listeners\RefreshTenantAwareDependencies::class,
12],

Tenancy bootstrappers are listeners that handle the Sprout\Evnts\CurrentTenantChanged event. Any classes that are listed here will be registered as listeners for that event. This option only exists to give you control over the process, whether you want to remove one of these, or add your own. If you are creating your own tenancy bootstrapper (event listener), you only actually need to add it to this array, if you need it to be called before one of these.

Service Overrides

The final part of the default configuration is the config/sprout/overrides.php file, which represents the sprout.overrides config option. Rather than having several smaller options within, this config file is the entire option itself, and lets you list out the service overrides that should be registered with Sprout, as well as any necessary configuration.

1return [
2 'filesystem' => [
3 'driver' => \Sprout\Overrides\StackedOverride::class,
4 'overrides' => [
5 \Sprout\Overrides\FilesystemManagerOverride::class,
6 \Sprout\Overrides\FilesystemOverride::class,
7 ],
8 ],
9 'job' => [
10 'driver' => \Sprout\Overrides\JobOverride::class,
11 ],
12 'cache' => [
13 'driver' => \Sprout\Overrides\CacheOverride::class,
14 ],
15 'auth' => [
16 'driver' => \Sprout\Overrides\StackedOverride::class,
17 'overrides' => [
18 \Sprout\Overrides\AuthGuardOverride::class,
19 \Sprout\Overrides\AuthPasswordOverride::class,
20 ],
21 ],
22 'cookie' => [
23 'driver' => \Sprout\Overrides\CookieOverride::class,
24 ],
25 'session' => [
26 'driver' => \Sprout\Overrides\SessionOverride::class,
27 'database' => false,
28 ],
29];

The reason this is a dedicated file is that service override configuration can start to get quite long. Service overrides are designed to make a "service" multitenanted. In the case of the default installation, this simply means components of Laravel, but would also include things like Livewire, Filament, Telescope, Nova, etc., etc.

It can get even worse; when like the auth and filesystem override, they're split into multiple parts. To find out more about the available service overrides, as well as service overrides as a concept, check out the documentation for them.