How yii2 handles multiple databases in console? - database

I have a Yii2 backend app with the following database schema (hundred of databases).
return [
'components' => [
'db1' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=mydb1',
'username' => 'my_username1',
'password' => 'my_password1',
],
'db2' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=mydb2',
'username' => 'my_username2',
'password' => 'my_password2',
],
....
],
];
The app is used by multiple companies.
Every time a user of a company logs in I save the company identifier in a session variable to be able to access the specific database of each company through getDb().
My problem is that I can't run console commands because I don't have access to the session.
Any idea to solve this problem?
Thanks in advance.

Related

Call Config::set to change database in Lumen 5.4? (Using Eloquent)

I have a small application in Lumen which should handle multiple databases based on the request URL. To make this possible in the first place I've created a folder /config/ and a config-file called /config/database.php. Here is the code and I added some comments to show what I exactly need to do.
<?php
return [
'migrations' => 'home',
'default' => 'home',
'connections' => [
// This is the default option and its needed to check if the "client" exists.
'home' => [
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'home',
'username' => 'root',
'password' => 'password',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
],
// When the client is found in the "home" connection, I'd like to continue with this database settings as default.
'client' => [
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'client_', // There is one database per client which in the end will look like this: "client_******", so I have to add this using Config:set...
'username' => 'root',
'password' => 'password',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
],
],
];
I have to call Config::set to change these settings but it doesnt seem to be available on Lumen. How can i change these settings (the default database connection and its database)
I hope there is a way to make this possible. Thanks a lot :)
I found the solution.
To set and edit your configuration use the "config" helper method with an array as argument.
Example:
config(['database.default' => 'your_connection']);
In a query you can use as follows:
$connectionClient = DB::connections('client');
$connectionHome = DB::connections('home');
I hope have helped.

Laravel - Set up dynamic database connection on Multi tenant application

Within my app I have different businesses and those have a number of users.
For example:
Business A has UserA, UserB and UserC
Business B has UserD and UserE
And so on..
Each business has its own separate database, so Users A, B and C access the same database, and Users D and E access a different database (Every tenant database is identical in structure, the only thing that differs is the data).
There is a main database that has this information for each user, so I know which database a user belongs.
'main' => array(
'driver' => 'mysql',
'host' => 'hostname',
'database' => 'main_database',
'username' => 'username',
'password' => 'password',
'prefix' => '',
),
'tenant' => array(
'driver' => 'mysql',
'host' => 'localhost',
'database' => DYNAMIC_DATABASE_NAME_GOES_HERE,
'username' => 'username',
'password' => 'password',
'prefix' => '',
),
I need to find a way to do the following in Laravel:
User signs in to the app
After login I get the user database identifier/database name using the main database connection
Set that specific database name within a connection called "tenant"
App uses that tenant connection to load the data of that specific
user/business
How can I accomplish this in Laravel 5.4?
This link has a very good example of what you are looking for.
1) Setup two connections in your database config.
'main' => array(
'driver' => 'mysql',
'host' => 'hostname',
'database' => 'database',
'username' => 'username',
'password' => 'password',
'prefix' => '',
),
'tenant' => array(
'driver' => 'mysql',
'host' => '',
'database' => '',
'username' => '',
'password' => '',
'prefix' => '',
)
2) Then to switch the DB, put the following code in your filters or middleware. Considering you have Tenant model for database connection info.
$tenant = Tenant::whereSubDomain($subdomain)->first();
Config::set('database.connections.tenant.host', $tenant ->host);
Config::set('database.connections.tenant.username', $tenant ->username);
Config::set('database.connections.tenant.password', $tenant ->password);
Config::set('database.connections.tenant.database', $tenant ->database);
//If you want to use query builder without having to specify the connection
Config::set('database.default', 'tenant');
\DB::purge('tenant');
\DB::reconnect('tenant');
dd(\DB::connection('tenant'));
3) Specify following in your models
//On models dealing with the main DB
protected $connection = 'main';
//On models dealing with tenant DBs
protected $connection = 'tenant';

cakephp3 multiple database connections with plugin not loading

I am trying to load some data from a plugin model which uses a different database. I have added an entry in my config/app.php as follows:
/**
* The test connection is used during the test suite.
*/
'alternate1' => [
'className' => 'Cake\Database\Connection',
'driver' => 'Cake\Database\Driver\Mysql',
'persistent' => false,
'host' => 'localhost',
//'port' => 'non_standard_port_number',
'username' => 'alt_user',
'password' => '********',
'database' => 'secondary_db',
'encoding' => 'utf8',
'timezone' => 'UTC',
'cacheMetadata' => true,
'quoteIdentifiers' => false,
'log' => false,
//'init' => ['SET GLOBAL innodb_stats_on_metadata = 0'],
'url' => env('DATABASE_TEST_URL', null),
],
In my plugin /plugins/Importer/src/Model/LogsTable.php class, I've added
public static function defaultConnectionName() {
return 'alternate1';
}
Now, I'd like to be able to access this data from my main applications controllers, so I tried this:
in /src/Controllers/ReviewController.php
$this->loadModel('Importer.Logs');
$logCount = $this->Logs->find('all')->count();
If I check the model like this:
print_r($this->Logs);
I see that it is still using the 'default' connection, and not the 'alternate1' connection.
Cake\ORM\Table Object ( [registryAlias] => Importer.Logs [table] => logs [alias] => Logs [entityClass] => \Cake\ORM\Entity [associations] => Array ( ) [behaviors] => Array ( ) [defaultConnection] => default [connectionName] => default )
I have also tried TableRegistry::get('Importer.Logs') and a few other variations, but in the end I am unable to get Cake to properly load the correct data connection.
I'm missing something simple here, I just know it. This answer: CakePHP 3 defaultConnectionName in plugin model doesn't work seems to be what I want, but it's not correct. I'm already using the Namespace.Model format.

Google App Engine Cloud SQL connection issue

When trying to connect to Google Cloud SQL I get following error:
Connection error
Unable to find the socket transport "unix" - did you forget to enable it when you configured PHP?
I have been trying to solve this issue now for multiple hours, still nothing.
My config is as follows (in ZF2 config local.php):
return array(
'db' => array(
'driver' => 'Mysqli',
'host' => '',
'database' => 'ar_captab',
'username' => 'root',
'password' => '',
'driver_options' => [
'unix_socket' => ':/cloudsql/some-app-v1-test:some-db'
]
),
);
I also added my application ID of my Google App Engine application to Access Control list (Authorized App Engine Applications) in Cloud SQL.
When I try to run this:
$config = $this->getServiceLocator()->get('config');
$adapter = new \Zend\Db\Adapter\Adapter($config['db']);
$sql = new \Zend\Db\Sql\Sql($adapter);
$select = $sql->select();
$select->from('example');
$select->where('1');
$statement = $sql->prepareStatementForSqlObject($select);
$results = $statement->execute();
I get the unix socket error. What I am missing?
Finally figured it out. I was because of the colon. You do not need it with Mysqli connection, only with PDO connection types.
So the correct config is:
return array(
'db' => array(
'driver' => 'Mysqli',
'host' => '',
'database' => 'some-database',
'username' => 'root',
'password' => '',
'driver_options' => [
'unix_socket' => '/cloudsql/some-app-v1-test:some-db'
]
),
);

cake console baking on different datasource (pluguin array)

I ve installed datasource plugin Array. It do NOT use db tables as source of data. Its an array (source). When i try to bake using cake bake (or something) it doesnt recognize the array source used, only the tables of my database.
I would like to bake all the crud actions as done for datasource database tables as my array datasource. how can i acomplish that ?
ty advance
After you setup your DataSources. If you running the bake command from your root directory where you can see bin folder.
This will give you list of tables
sudo bin/cake bake.bake model --connection OTHER_DATABASE_NAME
Let's say we want to bake for Users table
Bake a model
sudo bin/cake bake.bake model TABLE_NAME --connection OTHER_DATABASE_NAME
In cakephp 3.x
If you want to do it manually you can create your Entity class and Table class as normal. and then in UsersTable.php add this function:
public static function defaultConnectionName()
{
return 'OTHER_DATABASE_NAME';
}
When you use Cake Bake ( and i think other console commands ) cake will look at the default value in your DATABASE_CONFIG unless you use the "-c" option. It lets you choose a different data connection. You probably default set to your database and a different one for the array datasource.
try edit yout file app.php:
'Datasources' => [
'default' => [
'className' => 'Cake\Database\Connection',
'driver' => 'Cake\Database\Driver\Mysql',
'persistent' => false,
'host' => 'aws.amazon-br.service',
//'port' => 'non_standard_port_number',
'username' => 'username',
'password' => 'passaword',
'database' => 'wp_my_site',
'encoding' => 'utf8',
'timezone' => 'UTC',
'cacheMetadata' => true,
'quoteIdentifiers' => false,
'log' => false,
//'init' => ['SET GLOBAL innodb_stats_on_metadata = 0'],
'url' => env('DATABASE_TEST_URL', null),
],
/**
* The test connection is used during the test suite.
*/
'my_system_db' => [
'className' => 'Cake\Database\Connection',
'driver' => 'Cake\Database\Driver\Mysql',
'persistent' => false,
'host' => 'hostgator.dbsource.manager',
//'port' => 'non_standard_port_number',
'username' => 'my_systen',
'password' => 'secret_password',
'database' => 'my_system',
'encoding' => 'utf8',
'timezone' => 'UTC',
'cacheMetadata' => true,
'quoteIdentifiers' => false,
'log' => false,
//'init' => ['SET GLOBAL innodb_stats_on_metadata = 0'],
'url' => env('DATABASE_TEST_URL', null),
],
],
After saving the app.php file, go to yout pronpt and use the bake command this format:
cake bake all name_table -c name_your_connect
Example:
cake bake all users -c my_system_db

Resources