Multi-tenant SaaS built in Yii2 - php

I am working in a multi-tenant software (SaaS) built with yii2 on the Advanced Template, but I am not having the desired result about the tenants database connection.
I am trying to set the Database Connection as next in my config file for the frontend:
$defaultAdminDB = [
'class' => 'yii\db\Connection',
'dsn' => 'pgsql:host=localhost;dbname=untitled',
'username' => 'postgres',
'password' => 'myPass',
'charset' => 'utf8',
];
$config = [
'components' => [
'db' => function(){
if (Yii::$app->session->get('login', false)){
return [
'class' => 'yii\db\Connection',
'dsn' => Yii::$app->session->get('client_connection.dns'),
'username' => Yii::$app->session->get('client_connection.username'),
'password' => Yii::$app->session->get('client_connection.password'),
'charset' => 'utf8',
];
}
return [
'class' => 'yii\db\Connection',
'dsn' => 'pgsql:host=localhost;dbname=untitled',
'username' => 'postgres',
'password' => 'myPass',
'charset' => 'utf8',
];
},
'dbAdmin' => $defaultAdminDB
]
];
Then I have a two steps log in, where the first asks for the login (tenant id) and the next provides the user and password. On the first controller I do the next with:
$account = \frontend\models\AdminAccounts::findOne(['login'=>$this->login]);
if (!$account){
$this->addError('login', Yii::t('app', 'Account data not found.'));
return false;
}
$dns = sprintf('pgsql:host=%s;dbname=%s', $account->getAttribute('db_host'), $account->getAttribute('db'));
Yii::$app->session->set('login', $this->login);
Yii::$app->session->set('client_connection.dns', $dns);
Yii::$app->session->set('client_connection.username', $account->getAttribute('db_user'));
Yii::$app->session->set('client_connection.password', $account->getAttribute('db_pass'));
I get successfully the account (tenant) data and store it in session, but I guess my error is on instantiating the yii\db\Connection on the model's getDb() method.
Hope can help me.
Regards!

If you are changing the db connection info of an existing db connection then you should close the existing connection (Yii::$app->db->close()), change the connection info, and then open the new connection (Yii::$app->db->open()).

You can try
Yii::$app->db = new \yii\db\Connection([
'dsn' => Yii::$app->session->get('client_connection.dsn'),
'username' => Yii::$app->session->get('client_connection.username'),
'password' => Yii::$app->session->get('client_connection.password'),
]);

Related

Laravel validation 'exist' not working in master-slave DB configuration?

I am moving the project to Master-Slave configuration and got a problem, that validation related to DB stopped working for me. Any ideas what I'm missing?
so here is validation part:
$request->validate([
'property_id' => 'required|exists:mysql.property,p_id',
... other validations not related to DB ...
], $error_messages);
file config\database.php :
'mysql' => [
'driver' => 'mysql',
'write' => [
'host' => '196.168.56.211',
],
'read' => [
'host' => '192.168.56.222',
],
'port' => '3306',
'database' => 'project_db',
'username' => 'db_user',
'password' => 'pass123',
'unix_socket' => env('DB_SOCKET'),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
'engine' => null,
\PDO::ATTR_EMULATE_PREPARES => true,
],
this is what i'm reciving:
in file \vendor\laravel\framework\src\Illuminate\Database\Connection.php [663]:
catch (Exception $e) {
throw new QueryException(
$query, $this->prepareBindings($bindings), $e
);
}
SQLSTATE[HY000] [2002] An attempt to establish a connection was
unsuccessful, because The required response was not received from the
other computer within the required time, or the already established
connection was terminated due to the incorrect response of the already
connected computer. (SQL: select count(*) as aggregate from
property where p_id = 2444)
and this is happens when laravel try to connect to 'write' database.
But from MySQL workbench - connecting & editing records fine.
any ideas?
change your config to
'mysql' => [
'write' => [
'host' => '196.168.56.211'
],
'read' => [
'host' => '192.168.56.222',
],
'sticky' => true,
'driver' => 'mysql',
'database' => 'project_db',
'username' => 'db_user',
'password' => 'pass123',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
],
This ensures that any data written during the request cycle can be immediately read back from the database during that same request
official document read for more info

Using both mysql and redis in yii2 application

I'm building a CRM system which should allow a different access for different users, so i need to make a complex authentication and notifications in the panel. But the main system should use the REDIS. I have installed yii2 redis plugin and have the config like this in db.php (mysql config ):
<?php
return [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=yii2basic',
'username' => 'root',
'password' => '',
'charset' => 'utf8',
// Schema cache options (for production environment)
//'enableSchemaCache' => true,
//'schemaCacheDuration' => 60,
//'schemaCache' => 'cache',
];
And in web.php:
$db = require __DIR__ . '/db.php';
$config = [
'id' => 'basic',
'basePath' => dirname(__DIR__),
'bootstrap' => ['log'],
'aliases' => [
'#bower' => '#vendor/bower-asset',
'#npm' => '#vendor/npm-asset',
],
'components' => [
'redis' => [
'class' => 'yii\redis\Connection',
'hostname' => 'localhost',
'port' => 6379,
'database' => 0,
],
],
'db' => $db,
How can i differntiate my models, to use either mysql or redis? I assume if i specify redis in components section, the whole app uses redis db. I could use redis with multiple values for key, but since redis is dropping the keys when max memory will be reached, all registered users and their profiles will parish, so i think i should use mysql for this basci stuff ( database with roles, authentification, profiles)
return [
'components' => [
'db1' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=db1name', //maybe other dbms such as psql,...
'username' => 'db1username',
'password' => 'db1password',
],
'db2' => [
'class' => 'yii\redis\Connection',
'dsn' => 'YOURCONFIG',
'port' => '6379',
'password' => 'db2password',
'username' => 'db2username',
],
],
];
Then try to use
// To get from db1
Yii::$app->db1->createCommand((new \yii\db\Query)->select('*')->from('tbl_name'))->queryAll()
// To get from db2
Yii::$app->db2->createCommand((new \yii\db\Query)->select('*')->from('tbl_name'))->queryAll();
For active record in your model write
// db1
public function getDb() {
return Yii::$app->db1;
}
//Or db2
public function getDb() {
return Yii::$app->db2;
}

Yii2 advanced with MongoDB

I'm new to Yii2.
I want to use MongoDB with Yii2-advanced. For that, I have found this library:
https://github.com/yiisoft/yii2-mongodb
The issue is it doesn't explain much about the installation and configurations.
As the read me says I have added following into the common\config\main-local.php file:
'mongodb' => [
'class' => '\yii\mongodb\Connection',
'dsn' => 'mongodb://developer:password#localhost:27017/mydatabase',
],
But what should I do with the default db key which is there for of the MySQL connection:
'db' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=yii2_advanced_mongo',
'username' => 'root',
'password' => 'root',
'charset' => 'utf8',
],
If I comment out that db key and try to login, then it gives me following error:
Invalid Configuration – yii\base\InvalidConfigException
Unknown component ID: db
I think you should add the entry properly, if you want use the entry db for accessing your db datas you should comment the db entry related to mysql and assign db to your mongodb entry
'db' => [
'class' => '\yii\mongodb\Connection',
'dsn' => 'mongodb://your_user_name:your_password#localhost:27017/your_database',
],
//'db' => [
// 'class' => 'yii\db\Connection',
// 'dsn' => 'mysql:host=localhost;dbname=yii2_advanced_mongo',
// 'username' => 'root',
// 'password' => 'root',
// 'charset' => 'utf8',
//],

yii,migrate project to another server

I get a project from some provider and I try to migrate the site to another server and all lock fine only I can't make the connection to db.
The original code is this:
<?php
return [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=******',
'username' => 'root',
'password' => '********',
'charset' => 'utf8',
];
and the code then I modify is this
return [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost:3306;dbname=*******',
'username' => 'evoprom_user',
'password' => '********',
'charset' => 'utf8',
];
Do you have some idea?

Yii 2.0 : 2 database connection

I read this question yii 2.0 multiple database connection, and use the answer of #Ali MasudianPour.
I follow the first step:
First you need to configure your databases like below:
return [
'components' => [
'db1' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=database1',
'username' => 'root',
'password' => '',
'charset' => 'utf8',
],
'db2' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=database2',
'username' => 'root',
'password' => '',
'charset' => 'utf8',
],
],
]; ?>
But in my configuration in my db it gives me this error:
The configuration for the "db" component must contain a "class"
element.
This is because db component is main and required and you simply omitted its declaration.
Rename db1 and db2 for example to db and db1 accordingly:
return [
'components' => [
// Main connection
'db' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=database1',
'username' => 'root',
'password' => '',
'charset' => 'utf8',
],
// Another connection
'db1' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=database2',
'username' => 'root',
'password' => '',
'charset' => 'utf8',
],
],
]; ?>
Update:
Note that for the basic application db is configured in separate file config/db.php and then required in main config config/web.php like so:
'db' => require(__DIR__ . '/db.php'),
So you can configure main connection in db.php and add additional below as db1.
Simply you just have to create separate file for each database .
config/db ->
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=database1',
'username' => 'root',
'password' => '',
'charset' => 'utf8',
To access another db create file in config named db1.php add add another db configuration.
config/db1 ->
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=database2',
'username' => 'root',
'password' => '',
'charset' => 'utf8',
In config->web.php add
'db' => require(__DIR__ . '/db.php'),
'db1' => require(__DIR__ . '/db1.php'),
To access the Model:
public static function getDb() {
return Yii::$app->db1;
}

Categories