Merge Content and Structure Across DBs

Specs

Version
Drupal 7
Tools
Batch Processes
Field API
Created
19 Mar 2016

Summary

En circunstancias ideales, se puede utilizar el módulo de funciones para migrar estructura, tales como campos CCK, elementos de menú, vocabularios taxonomía, o variables del sistema, a la base de datos de producción.

Pero si lo que pone en circunstancias en las que esto no es posible, este fragmento le ayudará a migrar el contenido de su base de datos de la producción de nuevo a su entorno de desarrollo. A continuación, un volcado de la base de datos de desarrollo y la importación en la producción.

Para ello, utiliza un comando Drush en los siguientes pasos:

  1. Modificar la variable de bases de datos en $ settings.php para permitir múltiples bases de datos del sitio de Drupal. A continuación, utilice db_set_active ('nombre_base_de_datos') para alternar
  2. Bucle a través de una serie de bases de datos que almacenan las tablas de contenido, términos de la taxonomía, las presentaciones de formulario, y archivos administrados
  3. Truncar cada una de esas tablas en el desarrollo
  4. El uso de un comando de MySQL, mover todos los datos de las tablas de producción para las tablas de desarrollo
Drush Command Example
drush --user=1 example-migration

Code

1. settings.php modification

settings.php
MODULE_PATH/sites/default
Modify the $databases variable in your settings.php to allow for multiple databases. You can then use db_set_active('default') and db_set_active('production') to switch back and forth.
          
$databases = array(
  'default' => array(
    'default' => array(
      'database' => 'dev_db_name',
      'username' => 'dev_db_username',
      'password' => 'dev_db_password',
      'host' => 'localhost',
      'port' => '',
      'driver' => 'mysql',
      'prefix' => '',
    ),
  ),
  'production' => array(
    'default' => array(
      'database' => 'prod_db_name',
      'username' => 'prod_db_username',
      'password' => 'prod_db_password',
      'host' => 'localhost',
      'port' => '',
      'driver' => 'mysql',
      'prefix' => '',
    ),
  ),
);
          
          

2. Drush Command

MODULE_NAME.drush.inc
Add this to one of your modules by putting it in a file called MODULE_NAME.drush.inc. It will be auto discovered by Drush.
          
function MODULE_NAME_drush_command() {

  $items = array();

  $items['example-migration'] = array(
    'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_LOGIN,
  );

  return $items;
}

function drush_MODULE_NAME_example_migration() {

  $tables = array();

  // node
  $tables[] = 'node';
  $tables[] = 'node_access';
  $tables[] = 'node_comment_statistics';
  $tables[] = 'node_counter';
  $tables[] = 'node_revision';

  db_set_active('production'); // use the key from your $databases array in settings.php

  $schema = drupal_get_schema(NULL,TRUE);
  foreach ($schema as $table_name => $data) {
    if ((strpos($table_name, 'ield_data_') !== false) || (strpos($table_name, 'ield_revision_') !== false)) {
      $tables[] = $table_name;
    }
  }

  db_set_active('default');

  // taxonomy
  $tables[] = 'taxonomy_index';
  $tables[] = 'taxonomy_term_data';
  $tables[] = 'taxonomy_term_hierarchy';
  $tables[] = 'taxonomy_menu';

  // webforms
  $tables[] = 'webform';
  $tables[] = 'webform_submissions';
  $tables[] = 'webform_submitted_data';

  // other tables
  $tables[] = 'url_alias';
  $tables[] = 'field_collection_item';
  $tables[] = 'field_collection_revision';
  $tables[] = 'file_managed';
  $tables[] = 'file_usage';

  $batch = array(
    'operations' => array(),
    'title' => t('Processing Batch'),
    'init_message' => t('Process is starting.'),
    'progress_message' => t('Processed @current out of @total.'),
    'error_message' => t('Process has encountered an error.'),
    'file' => drupal_get_path('theme', 'MODULE_NAME') . '/MODULE_NAME.drush.inc',
    'finished' => 'MODULE_NAME_example_migration_batch_finished'
  );

  $start_time = time();

  $batch['progressive'] = FALSE;

  $batch['operations'][] = array('MODULE_NAME_example_migration_content_batch', array($tables, $start_time));

  drush_log(t('Batch process is starting !time', array('!time' => format_date($start_time, 'long'))), 'success');

  batch_set($batch);
  drush_backend_batch_process();

}

function MODULE_NAME_example_migration_content_batch($tables, $start_time, &$context) {

  set_time_limit(9999999);

  foreach ($tables as $key => $table_name) {
    if (db_table_exists($table_name)) {
      $results = db_query("TRUNCATE development_database_name." . $table_name . ";");
      $results = db_query("INSERT INTO development_database_name." . $table_name . " SELECT * FROM production_database_name." . $table_name . ";");
    }
    else {
      drush_log(t('Dev database is missing table !table_name but it exists in production.', array('!table_name' => $table_name)), 'warning');
    }
  }

  $context['results']['start_time'] = $start_time;

}

function MODULE_NAME_example_migration_batch_finished($success, $results, $operations) {
  if ($success) {

    $start_time = $results['start_time'];

    $seconds = time() - $start_time;
    $hours = floor($seconds / 3600);
    $mins = floor(($seconds - ($hours*3600)) / 60);
    $secs = floor($seconds % 60);

    drush_log(t('Job completed in: !hours hours !mins minutes !secs seconds', array('!hours' => $hours, '!mins' => $mins, '!secs' => $secs)), 'success');
  }
  else {
    $error_operation = reset($operations);
    $message = t('An error occurred while processing %error_operation with arguments: @arguments', array('%error_operation' => $error_operation[0], '@arguments' => print_r($error_operation[1], TRUE)));
    drush_log($message, 'error');
  }
}
          
          

Comments

Placeholder: I'll extend node comments with ajax and other functionality here.