Skip to content

Misc

Misc

Customizing database creation

You can use tenancy_db_* attributes when creating a tenant to specify how the database should be created. (You can also set those attributes after creation to make the tenant use an existing database.)

How it works:

  • tenancy_db_connection will make the tenant get created on that connection instead of the default central one, and that connection will become the base connection for the tenant. Meaning, their database config will be the tenancy_db_connection plus any custom fields (like a custom DB name).
  • tenancy_db_name has a special meaning — it tells Tenancy what to name the database that will be created.
  • All other fields simply become part of the tenant database config, for example tenancy_db_host and tenancy_db_port will make the tenant use a different DB server.
  • Any fields that can be used in database.connections.* config can be used here.

Some notes:

  • If no tenancy_db_connection is specified, the default central connection will be used as the base.
  • Laravel requires a database name to create a connection, this means if you simply want to use:
    Tenant::create(['tenancy_db_host' => 'mysql2']);
    Tenancy will try to connect to the database from your central DB’s config on that host, and then create the database. This means that the database set as DB_DATABASE needs to exist on that server, even if it won’t be used for anything (besides creating the connection). You can bypass this by creating a dummy database on that server, and connecting to that:
    Tenant::create(['tenancy_db_host' => 'mysql2', 'tenancy_db_name' => 'dummy_database']);
    Alternatively, if your database server allows it, you can connect to some built-in database:
    Tenant::create(['tenancy_db_host' => 'mysql2', 'tenancy_db_name' => 'information_schema']);
    Connecting to information_schema is safe as it’s a read-only database.
  • If you have a couple of servers across which you distribute your tenants, it’s recommended to create dedicated connections. That way you’ll only specify tenancy_db_connection on those tenants and won’t need to manage the connection details across multiple tenant records. It will be easier to make changes and keep your tenant models cleaner.

Make sure to also check the docs section on specifying the template connection using array syntax for some potential simplifications.

Integrating with packages

  • Mention that the clone routes action can also be used to create tenant routes, not just universal routes

Database connections

  • If you are using multi-database tenancy, the package might be working with two database connections at times which may reduce performance.
    • By default, the package only queries the central database during tenant identification. These queries can be prevented by using Cached Resolvers
    • When Cached Resolvers are used, the central connection will not be established for tenant identification, as the package stores a cached version of the Tenant model (this cache is efficiently cleared whenever there are changes made to any tenant). However, the central connection may still be created if you make direct queries to the central database in your own code (e.g. updating Tenant objects, using tenancy()->central() calls etc).

Reserved middleware

tenant, central, universal are reserved by the package

MailTenancyBootstrapper

Enabling MailTenancyBootstrapper allows you to use tenant attributes as mailer credentials. To enable the bootstrapper, uncomment it in your tenancy.php config file (tenancy.bootstrappers).

The bootstrapper maps tenant attributes specified in the customizable $credentialsMap static property to config. The following code updates the mail.mailers.smtp.username config key to the tenant’s smtp_username attribute (if the tenant has that attribute) when Tenancy gets bootstrapped:

TenancyServiceProvider.php
TenancyServiceProvider
public function boot()
{
// ...
MailTenancyBootstrapper::$credentialsMap = [
'mail.mailers.smtp.username' => 'smtp_username',
];
}

You can also define map presets for different mailers in the static $mapPresets property. The property has a SMTP preset by default, but feel free to customize it.

TenancyServiceProvider.php
public function boot()
{
// ...
// MailTenancyBootstrapper::$mapPresets['mailer_name'] = ['config.key' => 'tenant_attribute_name']
MailTenancyBootstrapper::$mapPresets['smtp'] = [
'mail.mailers.smtp.host' => 'smtp_host',
'mail.mailers.smtp.port' => 'smtp_port',
'mail.mailers.smtp.username' => 'smtp_username',
'mail.mailers.smtp.password' => 'smtp_password',
];
}

By default, the bootstrapper will automatically choose the map preset for your default mailer (config('mail.default')) from $mapPresets and merge that with $credentialsMap. You can make the bootstrapper use a different mailer by updating the static $mailer property.

Queueing mail

To make the config update correctly and allow the mailer to use the correct credentials while queueing the mail, QueueTenancyBootstrapper’s $forceRefresh property has to be set to true.

Ziggy

  • Ziggy needs URL::defaults(), our URL generator override doesn’t work