skip to Main Content

I can’t get the stancl/multitenancy package configured with with my Laravel 8/Fortify/Jetstream app. I’m using subdomain tenant identification and I’m getting the following error on all routes:

SQLSTATE[3D000]: Invalid catalog name: 1046 No database selected (SQL: select * from sessions where id = BZmFIzeqXoJbwJkt6iiSwj7lD8EZH6I2hsyexUFv limit 1)
Here are my configurations:

I think it has something to do with the way Fortify works. Any help is highly appreciated!

.env

DB_CONNECTION_CENTRAL=central
DB_CONNECTION_TENANT=tenancy_db_connection
SESSION_DRIVER=database

routes/tenant.php

Route::middleware([
    InitializeTenancyBySubdomain::class,
    PreventAccessFromCentralDomains::class,
    'auth:sanctum',
    'web',
])->group(function () {

config/database.php

'connections' => [

        'central' => [
            'driver' => 'mysql',
            'url' => env('DATABASE_URL'),
            'host' => env('DB_HOST', '127.0.0.1'),
            'port' => env('DB_PORT', '3306'),
            'database' => env('DB_DATABASE_CENTRAL', 'forge'),
            'username' => env('DB_USERNAME', 'forge'),
            'password' => env('DB_PASSWORD', ''),
            'unix_socket' => env('DB_SOCKET', ''),
            'charset' => 'utf8mb4',
            'collation' => 'utf8mb4_unicode_ci',
            'prefix' => '',
            'prefix_indexes' => true,
            'strict' => true,
            'engine' => null,
            'options' => extension_loaded('pdo_mysql') ? array_filter([
                PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
            ]) : [],
        ],

        'tenancy_db_connection' => [
            'driver' => 'mysql',
            'url' => env('DATABASE_URL'),
            'host' => env('DB_HOST', '127.0.0.1'),
            'port' => env('DB_PORT', '3306'),
            'database' => null,
            'username' => env('DB_USERNAME', 'forge'),
            'password' => env('DB_PASSWORD', ''),
            'unix_socket' => env('DB_SOCKET', ''),
            'charset' => 'utf8mb4',
            'collation' => 'utf8mb4_unicode_ci',
            'prefix' => '',
            'prefix_indexes' => true,
            'strict' => true,
            'engine' => null,
            'options' => extension_loaded('pdo_mysql') ? array_filter([
                PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
            ]) : [],
        ],
    ],

config/session.php

    'driver' => env('SESSION_DRIVER', 'database'),
    'connection' => env('DB_CONNECTION_TENANT', 'tenancy_db_connection'),

config/fortify.php

    'middleware' => [
        'web',
        StanclTenancyMiddlewareInitializeTenancyBySubdomain::class
    ],

config/jetstream.php

    'middleware' => ['web'],

config/tenancy.php

<?php

declare(strict_types=1);

use StanclTenancyDatabaseModelsDomain;
use AppModelsTenant;

return [
    'tenant_model' => Tenant::class,
    'id_generator' => StanclTenancyUUIDGenerator::class,
    'domain_model' => Domain::class,

    /**
     * The list of domains hosting your central app.
     *
     * Only relevant if you're using the domain or subdomain identification middleware.
     */
    'central_domains' => [
        {{ LOCAL_VALET_DOMAIN }},
        {{ PROD_DOMAIN }}
    ],

    /**
     * Tenancy bootstrappers are executed when tenancy is initialized.
     * Their responsibility is making Laravel features tenant-aware.
     *
     * To configure their behavior, see the config keys below.
     */
    'bootstrappers' => [
        StanclTenancyBootstrappersDatabaseTenancyBootstrapper::class,
        StanclTenancyBootstrappersCacheTenancyBootstrapper::class,
        StanclTenancyBootstrappersFilesystemTenancyBootstrapper::class,
        StanclTenancyBootstrappersQueueTenancyBootstrapper::class,
        // StanclTenancyBootstrappersRedisTenancyBootstrapper::class, // Note: phpredis is needed
    ],

    /**
     * Database tenancy config. Used by DatabaseTenancyBootstrapper.
     */
    'database' => [
        'central_connection' => env('DB_CONNECTION_CENTRAL', 'central'),

        /**
         * Connection used as a "template" for the tenant database connection.
         */
        'template_tenant_connection' => env('DB_CONNECTION_TENANT', 'tenancy_db_connection'),

        /**
         * Tenant database names are created like this:
         * prefix + tenant_id + suffix.
         */
        'prefix' => 'tenant',
        'suffix' => '',

        /**
         * TenantDatabaseManagers are classes that handle the creation & deletion of tenant databases.
         */
        'managers' => [
            'sqlite' => StanclTenancyTenantDatabaseManagersSQLiteDatabaseManager::class,
            'mysql' => StanclTenancyTenantDatabaseManagersMySQLDatabaseManager::class,
            'pgsql' => StanclTenancyTenantDatabaseManagersPostgreSQLDatabaseManager::class,

            /**
             * Use this database manager for MySQL to have a DB user created for each tenant database.
             * You can customize the grants given to these users by changing the $grants property.
             */
            // 'mysql' => StanclTenancyTenantDatabaseManagersPermissionControlledMySQLDatabaseManager::class,

            /**
             * Disable the pgsql manager above, and enable the one below if you
             * want to separate tenant DBs by schemas rather than databases.
             */
            // 'pgsql' => StanclTenancyTenantDatabaseManagersPostgreSQLSchemaManager::class, // Separate by schema instead of database
        ],
    ],

    /**
     * Cache tenancy config. Used by CacheTenancyBootstrapper.
     *
     * This works for all Cache facade calls, cache() helper
     * calls and direct calls to injected cache stores.
     *
     * Each key in cache will have a tag applied on it. This tag is used to
     * scope the cache both when writing to it and when reading from it.
     *
     * You can clear cache selectively by specifying the tag.
     */
    'cache' => [
        'tag_base' => 'tenant', // This tag_base, followed by the tenant_id, will form a tag that will be applied on each cache call.
    ],

    /**
     * Filesystem tenancy config. Used by FilesystemTenancyBootstrapper.
     * https://tenancyforlaravel.com/docs/v3/tenancy-bootstrappers/#filesystem-tenancy-boostrapper.
     */
    'filesystem' => [
        /**
         * Each disk listed in the 'disks' array will be suffixed by the suffix_base, followed by the tenant_id.
         */
        'suffix_base' => 'tenant',
        'disks' => [
            'local',
            'public',
            // 's3',
        ],

        /**
         * Use this for local disks.
         *
         * See https://tenancyforlaravel.com/docs/v3/tenancy-bootstrappers/#filesystem-tenancy-boostrapper
         */
        'root_override' => [
            // Disks whose roots should be overriden after storage_path() is suffixed.
            'local' => '%storage_path%/app/',
            'public' => '%storage_path%/app/public/',
        ],

        /**
         * Should storage_path() be suffixed.
         *
         * Note: Disabling this will likely break local disk tenancy. Only disable this if you're using an external file storage service like S3.
         *
         * For the vast majority of applications, this feature should be enabled. But in some
         * edge cases, it can cause issues (like using Passport with Vapor - see #196), so
         * you may want to disable this if you are experiencing these edge case issues.
         */
        'suffix_storage_path' => true,

        /**
         * By default, asset() calls are made multi-tenant too. You can use global_asset() and mix()
         * for global, non-tenant-specific assets. However, you might have some issues when using
         * packages that use asset() calls inside the tenant app. To avoid such issues, you can
         * disable asset() helper tenancy and explicitly use tenant_asset() calls in places
         * where you want to use tenant-specific assets (product images, avatars, etc).
         */
        'asset_helper_tenancy' => true,
    ],

    /**
     * Redis tenancy config. Used by RedisTenancyBoostrapper.
     *
     * Note: You need phpredis to use Redis tenancy.
     *
     * Note: You don't need to use this if you're using Redis only for cache.
     * Redis tenancy is only relevant if you're making direct Redis calls,
     * either using the Redis facade or by injecting it as a dependency.
     */
    'redis' => [
        'prefix_base' => 'tenant', // Each key in Redis will be prepended by this prefix_base, followed by the tenant id.
        'prefixed_connections' => [ // Redis connections whose keys are prefixed, to separate one tenant's keys from another.
            // 'default',
        ],
    ],

    /**
     * Features are classes that provide additional functionality
     * not needed for tenancy to be bootstrapped. They are run
     * regardless of whether tenancy has been initialized.
     *
     * See the documentation page for each class to
     * understand which ones you want to enable.
     */
    'features' => [
        // StanclTenancyFeaturesUserImpersonation::class,
        // StanclTenancyFeaturesTelescopeTags::class,
         StanclTenancyFeaturesUniversalRoutes::class,
        // StanclTenancyFeaturesTenantConfig::class, // https://tenancyforlaravel.com/docs/v3/features/tenant-config
        // StanclTenancyFeaturesCrossDomainRedirect::class, // https://tenancyforlaravel.com/docs/v3/features/cross-domain-redirect
    ],

    /**
     * Parameters used by the tenants:migrate command.
     */
    'migration_parameters' => [
        '--force' => true, // This needs to be true to run migrations in production.
        '--path' => [database_path('migrations/tenant')],
        '--realpath' => true,
    ],

    /**
     * Parameters used by the tenants:seed command.
     */
    'seeder_parameters' => [
        '--class' => 'DatabaseSeeder', // root seeder class
        // '--force' => true,
    ],
];

2

Answers


  1. Your database for is null for tenant. have you made one for tenant? make sure check it again in database if no, create one and try to reinstall the tenant subdomain.

    Login or Signup to reply.
  2. Copy or move create_sessions_table.php file in database/migrations to database/migrations/tenant folder and run the below code in your terminal,

    php artisan tenants:migrate
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search