DEV Community

Cover image for Runtime Configuration of Source Migration Database for Drupal 9/10/11
Tanmay Khedekar
Tanmay Khedekar

Posted on

Runtime Configuration of Source Migration Database for Drupal 9/10/11

When working with Drupal migrations, the source database credentials are typically defined in settings.php. However, in many cases you may want to allow these credentials to be configurable at runtime so that they can be easily managed across different environments.

In this guide, I'll walk you through a solution that lets you dynamically configure the migration database. The idea is to provide a configuration form (which isn’t covered here) that saves your database connection details. Then, we leverage these saved details during the migration process.

Step 1: Create a Base Migration Class

First, create a file called ExampleSqlBase.php in your module (example) under the src directory. This class extends Drupal's SqlBase and implements ContainerFactoryPluginInterface to inject the configuration service. The code snippet below demonstrates how to retrieve your database configuration from the example.settings config and set up the connection accordingly:

<?php

namespace Drupal\example;

use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\State\StateInterface;
use Drupal\migrate\Plugin\migrate\source\SqlBase;
use Drupal\migrate\Plugin\MigrationInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Base class to use for all source migration plugins.
 */
abstract class ExampleSqlBase extends SqlBase implements ContainerFactoryPluginInterface {

  /**
   * The configuration name for migration settings.
   */
  const CONFIG_NAME = 'example.settings';

  /**
   * The config factory.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  protected $configFactory;

  /**
   * {@inheritdoc}
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, StateInterface $state, ConfigFactoryInterface $config_factory) {
    $this->configFactory = $config_factory;

    // Get the configuration.
    $migrate_config = $this->configFactory->get(self::CONFIG_NAME);
    $database_info = [
      'database' => [
        'database' => $migrate_config->get('database'),
        'username' => $migrate_config->get('username'),
        'password' => $migrate_config->get('password'),
        'host' => $migrate_config->get('host'),
        'port' => $migrate_config->get('port'),
        'driver' => $migrate_config->get('driver'),
        'namespace' => $migrate_config->get('namespace'),
        'prefix' => $migrate_config->get('prefix'),
      ],
      'key' => 'migrate',
      'target' => 'default',
    ];
    // Set up the database.
    $this->setUpDatabase($database_info);

    parent::__construct($configuration, $plugin_id, $plugin_definition, $migration, $state);
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, ?MigrationInterface $migration = NULL) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $migration,
      $container->get('state'),
      $container->get('config.factory')
    );
  }

}
Enter fullscreen mode Exit fullscreen mode

Step 2: Create a Source Migration Plugin

With the base class in place, creating a migration plugin is as simple as extending ExampleSqlBase. Below is an example of a source plugin named ExampleArticles that pulls data for articles content:

<?php

namespace Drupal\example\Plugin\migrate\source;

use Drupal\example\ExampleSqlBase;

/**
 * Source plugin for articles.
 *
 * @MigrateSource(
 *   id = "example_articles",
 * )
 */
class ExampleArticles extends ExampleSqlBase {

  /**
   * {@inheritdoc}
   */
  public function query() {
    $query = $this->select('node', 'n');
    $query->leftJoin('node_revision', 'nr', 'nr.nid = n.nid AND nr.vid = n.vid');
    $query->leftJoin('node_field_data', 'nf', 'nf.nid = n.nid AND n.vid = nf.vid');
    $query->fields('n', ['nid']);
    $query->fields('nf', ['langcode', 'title', 'status', 'created', 'changed', 'promote', 'sticky']);
    $query->condition('n.type', 'article');
    $query->orderBy('n.nid');
    // If your migrations require additional joins or fields,
    // you can further extend the query as needed.
    return $query;
  }

  /**
   * {@inheritdoc}
   */
  public function fields() {
    $fields = [
      'nid' => $this->t('ID'),
      'langcode' => $this->t('Language code'),
      'title' => $this->t('Title'),
      'status' => $this->t('Status'),
      'created' => $this->t('Created'),
      'changed' => $this->t('Updated'),
      'promote' => $this->t('Promoted'),
      'sticky' => $this->t('Sticky'),
    ];

    return $fields;
  }

  /**
   * {@inheritdoc}
   */
  public function getIds() {
    return [
      'nid' => [
        'type' => 'integer',
        'alias' => 'n',
      ],
    ];
  }

}
Enter fullscreen mode Exit fullscreen mode

Final Notes

Once the source database credentials are configured via your form, the above setup will enable your migration plugins to use those credentials dynamically.

Happy migrating!

Top comments (0)