I have an application that will be used by many databases. To choose the database with the application data I have a database with the connections parameters (host, username, pass, database...)
The problem is that this dynamically created datasource does not work for the rest of the application.
Controller Code
$data = $this->request->data;
$connection = ConnectionManager::get("default");
$query = "SELECT * FROM clients WHERE client_id = ".$data['codigo'];
$result = $connection->execute($query)->fetchAll('assoc');
ConnectionManager::drop('default');
$config = ConnectionManager::config('connection', [
'className' => 'Cake\Database\Connection',
'driver' => 'Cake\Database\Driver\Mysql',
'persistent' => false,
'host' => $result[0]['host'],
'username' => $result[0]['username'],
'password' => $result[0]['password'],
'database' => $result[0]['database'],
'encoding' => 'utf8',
'timezone' => 'UTC',
'flags' => [],
'cacheMetadata' => true,
'log' => false,
'quoteIdentifiers' => false,
'url' => env('DATABASE_URL', null),
]);
$connection = ConnectionManager::get('connection');
ConnectionManager::alias('connection', 'default');
return $this->redirect(['controller' => 'Mains', 'action' => 'index']);
After this redirect, apparently the other controllers do not have this datasource.
It's certainly a bit unusual to be swapping databases based on contents inside request data - but generally database connection just needs to be done earlier on in Cake's initial setup, as each Controller's connection resource is already set to the default
.
If you're only swapping the one time, you could manage this inside config/bootstrap.php
(where Cake normally sets up it's ConnectionManager) instead.
You won't have access to $this->request
, but could just grab it from $_REQUEST instead, for example:
In config/bootstrap.php
, change these lines:
Cache::config(Configure::consume('Cache'));
ConnectionManager::config(Configure::consume('Datasources'));
Email::configTransport(Configure::consume('EmailTransport'));
To this:
Cache::config(Configure::consume('Cache'));
ConnectionManager::config(Configure::consume('Datasources'));
$connection = ConnectionManager::get("default");
$client = TableRegistry::get('Clients')->find()
->where(['client_id'=> $_REQUEST['client_id']])->firstOrFail();
ConnectionManager::drop('default');
$config = ConnectionManager::config('connection', [
'className' => 'Cake\Database\Connection',
'driver' => 'Cake\Database\Driver\Mysql',
'persistent' => false,
'host' => $client->host,
'username' => $client->username,
'password' => $client->password,
'database' => $client->database,
'encoding' => 'utf8',
'timezone' => 'UTC',
'flags' => [],
'cacheMetadata' => true,
'log' => false,
'quoteIdentifiers' => false,
'url' => env('DATABASE_URL', null),
]);
ConnectionManager::get('connection');
Email::configTransport(Configure::consume('EmailTransport'));
Edited: Switched from your raw SQL to a Table::find()