Skip to content

Request Validator not working with tenant DB even tenant is active (fix attached to verify) #604

@Gkiokan

Description

@Gkiokan

I just got this issue where I couldn't validate my unique condition in my Request Validator.
Debugging it shows that the DB facade in the Validator ($request->validate(..)) was using the landlord default connection even the Model connection was set to the correct tenant.

To fix this, I've added a fix to my own Switch Tenant DB Task, you can see below.

If this is not the right way, what would it be?

<?php

namespace App\Services;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
use Spatie\Multitenancy\Concerns\UsesMultitenancyConfig;
use Spatie\Multitenancy\Contracts\IsTenant;
use Spatie\Multitenancy\Exceptions\InvalidConfiguration;

class SwitchTenantDatabaseTask extends \Spatie\Multitenancy\Tasks\SwitchTenantDatabaseTask
{

    public function makeCurrent(IsTenant $tenant): void
    {
        $this->setTenantConnectionDatabaseName($tenant->getDatabaseName());
    }

    public function forgetCurrent(): void
    {
        $this->setTenantConnectionDatabaseName(null);
    }

    protected function setTenantConnectionDatabaseName(?string $databaseName): void
    {
        $tenantConnectionName = $this->tenantDatabaseConnectionName();

        if ($tenantConnectionName === $this->landlordDatabaseConnectionName()) {
            throw InvalidConfiguration::tenantConnectionIsEmptyOrEqualsToLandlordConnection();
        }

        if (is_null(config("database.connections.{$tenantConnectionName}"))) {
            throw InvalidConfiguration::tenantConnectionDoesNotExist($tenantConnectionName);
        }

        config([
            "database.connections.{$tenantConnectionName}.database" => $databaseName,
        ]);

        app('db')->extend($tenantConnectionName, function ($config, $name) use ($databaseName) {
            $config['database'] = $databaseName;

            return app('db.factory')->make($config, $name);
        });

        DB::purge($tenantConnectionName);

        // Octane will have an old `db` instance in the Model::$resolver.
        Model::setConnectionResolver(app('db'));

        // Adding fixes to make DB Facade to be aware of the tenant connection 
        if ($databaseName) {
            config(['database.default' => $tenantConnectionName]);
            DB::purge();
        } else {
            // When forgetting, switch back to landlord
            config(['database.default' => $this->landlordDatabaseConnectionName()]);
            DB::purge();
        }        
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions