eiriksm.dev: Querying the migrate database from custom code

If you have made a couple of migrations for Drupal 8, you might have encountered the fact that some time you actually forgot something, or maybe your migration actually had a bug? But you already launched the site, so doing a new migration is out of the question. What do you do? Well, an update hook can save your day.

So, you might go ahead and write that update hook. And this update hook might want to do some queries in the old database. How do you then write mysql queries to the databse you have defined as the migrate database? After I first discovered this, I find myself searching for the code snippets where I did do this, so I decided to instead put this in a blog post as a reference for myself.

A pretty common way of having your databases defined in such cases would be like this:

$databases['default']['default'] = array (
  'database' => 'my_database',
  'username' => 'user',
  'password' => 'pass',
  'prefix' => '',
  'host' => 'localhost',
  'port' => '',
  'namespace' => 'Drupal\Core\Database\Driver\mysql',
  'driver' => 'mysql',
);
$databases['migrate']['default'] = array (
  'database' => 'my_old_database',
  'username' => 'user',
  'password' => 'pass',
  'prefix' => '',
  'host' => 'localhost',
  'port' => '',
  'namespace' => 'Drupal\Core\Database\Driver\mysql',
  'driver' => 'mysql',
);

What we want to do in our update hook is to get the connection information for the one in the ‘migrate’ key, so we can do queries in the migrate database. And we want to do it properly, right? Not just hardcode credentials and use any old sql client?

So what I usually do is this:

// The 2 arguments should correspond to the database target and key. The key in
// our example is 'migrate' and the target is 'default'.
/** @var DrupalCoreDatabaseConnection $db */
$db = DrupalCoreDatabaseDatabase::getConnection('default', 'migrate');
// Db is now a connection, the same as you would get if you would use the
// service "database". You can proceed to call methods on it like this:
$gifs = $db->select('file_managed', 'fm')
  ->fields('fm')
  ->condition('fm.filemime', 'image/gif')
  ->execute();
foreach ($gifs as $gif) {
  // Do something with the gif.
}

If you find yourself using this a lot, you can also create a service for it. You can use this pattern to define the service:

my_module.migrate_db:
  class: DrupalCoreDatabaseConnection
  factory: DrupalCoreDatabaseDatabase::getConnection
  # The 2 arguments should correspond to the database target and key. The key
  # in our example is 'migrate' and the target is 'default'.
  arguments: [default, migrate]

And then you can use it like this:

/** @var DrupalCoreDatabaseConnection $db */
$db = Drupal::service('my_module.migrate_db');
// Db is now a connection, the same as you would get if you would use the
// service "database". You can proceed to call methods on it like this:
$gifs = $db->select('file_managed', 'fm')
  ->fields('fm')
  ->condition('fm.filemime', 'image/gif')
  ->execute();
foreach ($gifs as $gif) {
  // Do something with the gif.
}

So that is 2 ways you can get the connection for your migrate database. Hope that helps someone out there!

To celebrate, lets have a look at an animated gif called “database”.