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 database you have defined as the migrate database? After I first discovered this, I found 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 with 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 \Drupal\Core\Database\Connection $db */$db = \Drupal\Core\Database\Database::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: Drupal\Core\Database\Connection factory: Drupal\Core\Database\Database::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 \Drupal\Core\Database\Connection $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”.