Ad

Laravel Modify Eloquent To Have A Variable Connection To Tenant Database

- 1 answer

This is a similar situation:

Multi tenancy in Laravel Eloquent ORM

I would like to modify eloquent model to have a variable database connection name. I have the name available as a string. I will have hundreds of models connecting to a tenant database, so I want a one-liner...

I have tried several approaches. The one that works is this:

$posUser = new posUser();
$posUser->setConnection($this->system->getDBC());
$posUser->create($posUserData);

with the classes set up like this:

class posUser extends myModel
{
}
class myModel extends Model
{
    public function setConnection($dbc)
    {
        $this->connection = $dbc;
    }
}

However this is a bit verbose. What I want is a one liner:

posUser::create($posUserData);

Which, I do have this on liner working by creating a new database connection and setting that connection to the default, which happens when the registered user visits the site. I would feel more comfortable with a command like (which errors...)

posUser::On($connection_name)->create($posUserData);

And require all models using the tenant databases to specify the connection. I am simply terrified that one tenant will somehow write to another tenant database. Any ideas?

Ad

Answer

The Answer for me so far is to set a connection as the default, then operate as normal.

1) get the system connection information from a database using a "main" connection 2) create the tenant connection 3) set it to default

Then all the tenant models/queries you will not supply a connection to. The main connection for me is set as 'main'.

Tenant Connection class

class TenantDatabaseConnector
{
    public static function GetDBCPrefix()
    {
        return strtolower(env('DB_PREFIX')) .'_'.env('MAIN_DB_NAME') . '_';
    }
    public static function createTenantConnection(System $system)
    {
        if(! self::checkDB($system->dbc()))
        {
            dd('You sure there is a database named ' . $system->dbc());
        }
        $env = strtoupper(env('DB_PREFIX'));
        $connections = Config::get('database.connections');
        $tenant_connection = [
            'driver'    => 'mysql',
            'host'      => env($env . '_DB_HOST'),
            'database'  => $system->dbc(),
            'username'  => env($env. '_DB_USERNAME'),
            'password'  => env($env .'_DB_PASSWORD'),
            'charset'   => 'utf8',
            'collation' => 'utf8_unicode_ci',
            'prefix'    => '',
            'strict'    => false,
            'port' => '3306'
        ];
        $connections[$system->dbc()] = $tenant_connection;
        Config::set('database.connections', $connections);
        self::setDefaultDBC($system);
        return true;

    }
    public static function setDefaultDBC($system)
    {
        Config::set('database.default', $system->dbc());
    }
    public static function checkDB($dbc)
    {
        $sql = "SELECT SCHEMA_NAME FROM 
                INFORMATION_SCHEMA.SCHEMATA 
                WHERE SCHEMA_NAME = '". $dbc ."'";

        $dbexists = DB::connection('main')->select($sql);

        if(sizeof($dbexists) > 0)
        {
            return true;
        }
        return false;
    }

}

You see a $env variable which I am using to set local_, alpha_, beta_, testing_ prefixes to my databases.

Ad
source: stackoverflow.com
Ad