1
kint(Database::setActiveConnection('preview'));
\Drupal::logger('Little kitties')->info('Mau');
kint(Database::setActiveConnection('default'));

As my expectation this would create a watchdog entry in preview database. The entry got created in the default database instead.

This means, setActiveConnection() only affects direct queries (select and db_query..)? That would be really sad.

0

2 Answers 2

3

Database::setActiveConnection() doesn't influence those objects that already have a \Drupal\Core\Database\Connection object, which means that the following code will not use the preview connection for altering the database table.

use \Drupal\Core\Database\Database;

$schema = Database::getConnection()->schema();
$old_key = Database::setActiveConnection('preview');
$schema->addField($table, $field, $spec, $keys_new);
Database::setActiveConnection($old_key);

When you call \Drupal::logger(), you get a DbLog object that was already initialised before Database::setActiveConnection('preview') is executed, which means it will use the old connection.

To be able to use the new connection for logging, you should try creating a custom logger that uses the connection you want, without you setting the connection before calling its methods.

As side note, Database::setActiveConnection() returns the old key; it's easy to restore it: Just call again Database::setActiveConnection() passing the value returned from the previous call, as I did with the code I shown.

2

However it does not stands in the question precisely my intention was to "switch" the database connection in the background for all services in the system. If someone is interested, here is the solution for it. The only requirement of this, that you have to have all the different database credential arrays in your settings.php (or in local settings respectively):

use Drupal\Core\Database\Database;
use Drupal\Core\TypedData\Exception\MissingDataException;

class DatabaseSwitcher {

  private $defaultContainer;

  public function __construct() {
    $this->defaultContainer = \Drupal::getContainer();
  }

  public function changeToDifferentDb($database_key) {
    $this->overrideDatabaseService($database_key);
  }

  public function changeToDefaultDb() {
    \Drupal::setContainer($this->defaultContainer);
  }

  private function overrideDatabaseService($database_key) {
    $database = $this->getExistingDatabaseConnection($database_key);
    $container = \Drupal::getContainer();
    $container->set('database', $database);
    \Drupal::setContainer($container);
  }

  private function getExistingDatabaseConnection($database_key) {
    $db_info = Database::getConnectionInfo($database_key);
    if (!$db_info) {
      throw new MissingDataException(sprintf('The %s database key is not defined', $database_name));
    }
    return Database::getConnection('', $database_key);
  }

}
2
  • Nice solution! is it possible to change the entity manager also so that entities can be saved in the external database?
    – Hedeshy
    Commented Jan 17, 2018 at 15:59
  • I do thing so. However later on I had issues with the database switching. Since it was a very time consuming task, I had to give up searching for the right solution: \ So all I have now are foggy memories about this!
    – ssibal
    Commented Jan 18, 2018 at 14:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.