Cambiar de base de datos al ingresar

Hola Colisteros,

Estoy armando una aplicación Yii2 advanced con MySQL; lo que quiero es que los usuarios del Frontend al momento de ingresar su usuario y contraseña se defina la base de datos que le corresponde, de tal forma que cada empresa tenga su propia base de datos.

Resolví esto de la siguiente manera:

Creé una base de datos de administración "app_admin"; en esa base de datos tengo dos tablas "user" y "accounts"; la tabla "user" controla el acceso de los usuarios y si es correcto su usr y psw obtengo sus datos de cuenta donde entre otros tengo "accounts.dsn", "accounts.dbusr" y "accounts.dbpsw" que son los datos de acceso a la base de datos de la cuenta que le corresponde a ese usuario que está ingresando.

Tengo otra(s) base(s) de dato(s) para cada una de las cuentas "app_xxxx", "app_yyyy", etcétera.

Y en los códigos de esta forma:

"frontend/index.php"




...

$application = new yii\web\Application($config);


// is there a user logged?

if (!Yii::$app->user->isGuest) {

	// dynamic configuration for 'db' from user->account

    Yii::$app->db->dsn      = Yii::$app->user->identity->account->dsn;   //'mysql:host=localhost;dbname=app_xxxx';

    Yii::$app->db->username = Yii::$app->user->identity->account->dbusr; //'root';

    Yii::$app->db->password = Yii::$app->user->identity->account->dbpsw; //'';

    Yii::$app->db->charset  = 'utf8mb4';

}


$application->run();



"common/config/main-local.php"




<?php

return [

    'components' => [

        'db' => [

            'class' => 'yii\db\Connection',

        ],

        'db_admin' => [

            'class' => 'yii\db\Connection',

            'dsn' => 'mysql:host=localhost;dbname=app_admin',

            'username' => 'root',

            'password' => '',

            'charset' => 'utf8mb4',

        ],

  ...



"common/models/user.php"




...

class User extends ActiveRecord implements IdentityInterface

{

    ...


    public static function getDb()

    {

        // use the "db_admin" application component

        return \Yii::$app->db_admin;

    }


    public function getAccount()

    {

        return $this->hasOne(Accounts::className(), ['pin' => 'account_pin']);

    }


    ...



"backend/models/accounts.php"




...

class Accounts extends \yii\db\ActiveRecord

{

    ...


    public static function getDb()

    {

        // use the "db_admin" application component

        return \Yii::$app->db_admin;

    }


    ...



"common/models/LoginForm.php"




class LoginForm extends Model

{

    ...

    public function login()

    {

        if ( ($this->validate() ... ) ) {


            // dynamic configuration for 'db' from user->account

            Yii::$app->db->dsn      = $this->getUser()->account->dsn;   //'mysql:host=localhost;dbname=app_xxxx';

            Yii::$app->db->username = $this->getUser()->account->dbusr; //'root';

            Yii::$app->db->password = $this->getUser()->account->dbpsw; //'';

            Yii::$app->db->charset  = 'utf8mb4';


            return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600 * 24 * 30 : 0);

        } else {

            $this->addError('username', Yii::t('app', 'No tiene acceso a esta sección.'));

            return false;

        }

    }

    ...



Al iniciar la aplicación el usuario es un invitado y es mandado al login, el modelo de user y accounts están en la base de datos app_admin; si las credenciales del usuario son correctas se obtienen los datos de su cuenta para definir la base de datos que le corresponde por ejemplo "app_xxxx"; el resto de las consultas se hacen en esa base de datos.

Mis dudadas son:

¿Estoy haciendo lo correcto?

¿Es segura esta solución?

¿Hay alguna mejor forma de hacerlo?

Por otro lado; tengo algunas tablas que dependen de "user"; por ejemplo, tengo una relación muchos a muchos con una "junction table" entre usuarios y sucursales: user -> user_subsidiaries -> subsidiaries; Como ya quedamos; la tabla "user" está en la base de datos "app_admin" y la tabla "subsidiaries" está en cada una de las base de datos de cada cuenta.

¿Cómo se resuelven este tipo de relaciones?

Perdón por alargarme tanto y muchas gracias por su atención,

Saludos.

Saludos:

Hace varios años resolví este escenario con una solución parecida a la tuya pero para Yii1. Este wiki lo describe. Aunque es para Yii1 quizá te ayude en algo porque aunque la sintaxis de las 2 versiones es distinta, los conceptos son iguales. Buena suerte.

Gracias @JFReyes,

Esto se ve justamente como lo que necesito; lo voy a estudiar bien y lo comento.

Saludos.