it-swarm.com.de

Wie aktualisiere ich die Konfiguration eines Moduls?

Ich baue ein benutzerdefiniertes Modul in Drupal 8. Es enthält einige YAML-Konfigurationsdateien.

Während ich mich entwickle, muss ich die Konfiguration ändern und ergänzen, z. um ein weiteres Feld zu meiner benutzerdefinierten Entität hinzuzufügen.

Gegenwärtig ist die einzige Möglichkeit, Drupal] zu erhalten, um die Änderungen zu bemerken, die Deinstallation des Moduls und die Neuinstallation.

Gibt es eine Möglichkeit, Drupal) abzurufen, um zu überprüfen, ob die von Modulen bereitgestellten Konfigurationsdateien mit der aktiven Konfiguration übereinstimmen, und wenn nicht, die aktive Konfiguration zu aktualisieren? Wie werden Modulaktualisierungen behandelt? In D7 hook_update_N würde verwendet, um Felder mit PHP hinzuzufügen, aber es sieht so aus, als ob dies vom CM in D8 behandelt werden sollte?

Dinge, die ich nach dem Aktualisieren der yml-Dateien im Modul versucht habe:

  1. drush cr, Konfigurationssynchronisation.

  2. manuelles Kopieren aller aktualisierten Konfigurationsdateien in sites/default/files/config_XXX/staging/ - aber dies führt zu diesem Fehler "Die bereitgestellte Konfiguration kann nicht importiert werden, da sie von einer anderen Site als dieser Site stammt. Sie können die Konfiguration nur zwischen geklonten Instanzen dieser Site synchronisieren.".

  3. manuelles Importieren der Dateien nacheinander mit dem Konfigurationsmanager. Das funktioniert, aber natürlich muss es einen automatischeren Weg geben.

  4. [BEARBEITEN] Verwenden Sie das Modul config_update manuell, um Änderungen zu überprüfen und zur Konfiguration des Moduls zurückzukehren. Auch dies ist manuell.

BEARBEITEN: Von Konfiguration verwalten - Do's and Don'ts

NICHT

Versuchen Sie, die aktive Konfiguration auf Ihrer Site zu ändern, indem Sie die Dateien im Konfigurations-/Installationsverzeichnis eines Moduls ändern. Dies funktioniert NICHT, da Drupal nur aus diesem Verzeichnis liest, wenn das Modul installiert ist.

... aber Änderungen dort werden gehen passieren, es sei denn, Module sind an die Konfiguration gebunden, die sie in ihrer ersten Version benötigt haben, und werden möglicherweise niemals die Konfiguration aktualisieren oder hinzufügen.

Danke im Voraus.

32
artfulrobot

Wie in der ursprünglichen Frage und den nachfolgenden Kommentaren erwähnt, gibt es eine Vielzahl von Contrib-Modulen und manuellen Methoden, um dies zu erreichen.

Um dies automatisch oder auf benutzerdefinierte Weise zu tun, denke ich, dass hook_update_N() wahrscheinlich immer noch die praktikabelste Option ist.

Dies ist beispielsweise ein Beispiel aus dem Head 2 Head zum Aktualisieren von system.site um das default_langcode:

  $config_factory = \Drupal::configFactory();
  $langcode = $config_factory->get('system.site')->get('langcode');
  $config_factory->getEditable('system.site')->set('default_langcode', $langcode)->save();

Sie können auch die Konfiguration einlesen (empfohlen nur zum Hinzufügen einer neuen Konfiguration, nicht unbedingt zum Aktualisieren oder Überschreiben der möglicherweise angepassten Konfiguration):

  $source = new FileStorage($path);
  /** @var \Drupal\Core\Config\StorageInterface $active_storage */
  $active_storage = \Drupal::service('config.storage');
  $active_storage->write($name, $source->read($name));

wo $path ist der absolute Weg zum my_config.foo.yml Datei.

24
jhedstrom

Ich habe this Gist auf GitHub gefunden, das die Konfiguration des angegebenen Moduls mit drush zurücksetzt/neu lädt:

drush cim -y --partial --source=modules/path/to/module/config/install/
11
Елин Й.

Da ich auch auf diese Frage gestoßen bin, aber hier nicht wirklich die richtige Antwort für meine Situation gefunden habe, möchte ich eine weitere Antwort hinzufügen.

Bitte beachten Sie: Anti-Pattern voraus!

Anwendungsfall

Bei der Entwicklung von Projekten aktualisieren wir unsere Test-/Akzeptanzumgebung ständig mit neuen Konfigurationsupdates. Nehmen wir zum Beispiel ein einfaches fiktives News-Modul. Wir möchten dem Modul einen Inhaltstyp hinzufügen und diesen in unserer Akzeptanzumgebung bereitstellen. Nach der Überprüfung haben wir festgestellt, dass einige Felder und andere konfigurationsbezogene Dinge fehlen. Da wir wissen, dass die Akzeptanzumgebung in der Konfiguration nicht aktualisiert wird, möchten wir wirklich nur die gesamte Konfiguration aus dem Modul neu laden, während neue Funktionen hinzugefügt werden, und nicht durch das Importieren aller geänderten .yml Datei.

Wir benötigen unsere Konfiguration nur in Modulen, wenn wir Multisites entwickeln. Für einzelne Sites verwenden wir meist nur die exportierte Site-Konfiguration, bei der der nächste Schritt nicht erforderlich ist.

Konfiguration komplett neu importieren (Anti-Pattern!)

Wir haben festgestellt, dass wir mit dem Dienst ConfigInstaller die vollständige Konfiguration aus einem bestimmten Modul erneut importieren können.

// Implement in a update_N hook. 
\Drupal::service('config.installer')->installDefaultConfig('module', $module);

Mit Vorsicht verwenden!

Ich möchte hinzufügen, dass dadurch alle aktiven Inhalte überschrieben werden, die in der Umgebung geändert wurden. Verwenden Sie diese Lösung daher nur, wenn Sie sicher sind, dass die aktive Konfiguration sicher überschrieben werden kann. Wir werden dies niemals in einer Produktionsumgebung verwenden und nur in der frühen Entwicklung anwenden.

Probieren Sie zuerst die Lösung von @ jhedstrom aus, bevor Sie diese in Betracht ziehen.

10
Ambidex

Basierend auf meinem Kommentar: Wie aktualisiere ich die Konfiguration eines Moduls?

Wenn ich dem zweiten Ansatz folge, wird die Konfiguration in Drupal geschrieben, erhält jedoch keine UUID, selbst wenn ich sie in das Konfigurationsverzeichnis exportiere. Dies führte mich zu einem Problem, bei dem ich dies mit a versucht habe Benutzerdefinierte Ansicht. Auf der Übersichtsseite "Ansichten" wurde ein schwerwiegender Fehler zurückgegeben, da die UUID für die Entität "Konfiguration" nicht verfügbar war.

Ich habe eine kleine Funktion erstellt, die mir dabei hilft, hier mein Beispielcode:

function _example_views_update_config($configsNames) {
  $config_path    = drupal_get_path('module', 'example') . '/config/install';
  $source         = new FileStorage($config_path);
  $config_storage = \Drupal::service('config.storage');
  $config_factory = \Drupal::configFactory();
  $uuid_service = \Drupal::service('uuid');

  foreach ($configsNames as $name) {
    $config_storage->write($name, $source->read($name));
    $config_factory->getEditable($name)->set('uuid', $uuid_service->generate())->save();
  }
}

/**
 * Add new action configurations.
 */
function example_update_8003() {
  $configsNames = [
    'config-1',
    'config-2',
  ];

  _example_views_update_config($configsNames);
  return 'Added new configurations.';
}
2
Sebastian

Die obige Antwort (vollständiger Reimport) funktionierte auch für meinen Anwendungsfall, aber zuerst habe ich ein wenig über einen selektiveren Reimport nachgedacht. Hier ist der Code, den ich hatte, der als Update-Hook zu funktionieren schien und auf Code im Modul config_update basierte:

/**
 * Update all my config.
 *
 * This can be more selective than calling installDefaultConfig().
 */
function MYMODULE_update_8004() {
  $prefixes = [
    'field.storage.node',
    'field.field.node',
    'node.type',
    'core.base_field_override.node',
    'core.entity_view_display'
  ];
  $results = [];
  foreach ($prefixes as $prefix) {
    $results[$prefix] = _update_or_install_config($prefix);
  }
  $return = '';
  foreach ($results as $prefix => $result) {
    $return .= "\n$prefix:\n";
    foreach ($result as $key => $ids) {
      $return .= "$key: " . implode(', ', $ids) . "\n";
    }
  }
  if (function_exists('drush_log')) {
    drush_log($return, \Psr\Log\LogLevel::WARNING);
  }
  return $return;
}


/**
 * Update or install config entities from config/install files.
 *
 * @see \Drupal\config_update\ConfigReverter::import
 * @see \Drupal\config_update\ConfigReverter::revert
 *
 * @param string $prefix
 *   The prefix for YAML files in find, like 'field.storage.node'
 */
function _update_or_install_config($prefix) {
  $updated = [];
  $created = [];
  /** @var \Drupal\Core\Config\ConfigManagerInterface $config_manger */
  $config_manger = \Drupal::service('config.manager');
  $files = glob(__DIR__ . '/config/install/' . $prefix . '.*.yml');
  foreach ($files as $file) {
    $raw = file_get_contents($file);
    $value = \Drupal\Component\Serialization\Yaml::decode($raw);
    if (!is_array($value)) {
      throw new \RuntimeException(sprintf('Invalid YAML file %s'), $file);
    }
    // Lazy hack here since that code ignores the file extension.
    $type = $config_manger->getEntityTypeIdByName(basename($file));
    $entity_manager = $config_manger->getEntityManager();
    $definition = $entity_manager->getDefinition($type);
    $id_key = $definition->getKey('id');
    $id = $value[$id_key];
    /** @var \Drupal\Core\Config\Entity\ConfigEntityStorage $entity_storage */
    $entity_storage = $entity_manager->getStorage($type);
    $entity = $entity_storage->load($id);
    if ($entity) {
      $entity = $entity_storage->updateFromStorageRecord($entity, $value);
      $entity->save();
      $updated[] = $id;
    }
    else {
      $entity = $entity_storage->createFromStorageRecord($value);
      $entity->save();
      $created[] = $id;
    }
  }
  return [
    'updated' => $updated,
    'created' => $created,
  ];
}
1
pwolanin

Configuration Synchronizer Modul hilft, dieses Problem auf nette Weise zu lösen. Diese Modulsuite mit 7 Modulen scheint nur für diesen Fall etwas übertrieben zu sein (ihre Absicht besteht hauptsächlich darin, Updates sicher zusammenzuführen, ohne Anpassungen zu überschreiben), aber aufgrund ihres Konzepts ermöglicht sie auch das Verfolgen und Importieren von Konfigurationsänderungen von Modulen/install und/optionale Ordner schnell.

Grundsätzlich können Sie es wie folgt testen:

  • erstellen und aktivieren Sie Ihr benutzerdefiniertes Modul in Ihrer lokalen Umgebung, wobei einige "Standard" -Konfigurationselemente wie gewohnt im Ordner/config/install abgelegt werden
  • installieren und aktivieren Sie das Modul config_sync und alle zugehörigen Module
  • nehmen Sie einige Änderungen im Konfigurationselement Ihres Moduls im Ordner/config/install vor
  • access/admin/config/development/configuration/distro. Sie sollten Ihre Änderung sehen und die Option haben, sie in die aktive Konfiguration zu importieren (der Zusammenführungsmodus soll die Clientänderungen beibehalten, der Rücksetzmodus erzwingt den Import) - während der Entwicklung werde ich meistens den Rücksetzmodus verwenden, aber der Zusammenführungsmodus sollte auch funktionieren, es sei denn, Sie hat alle manuellen Änderungen in derselben Konfiguration parallel vorgenommen

Hinweis: Wenn Sie nur den config_sync verwenden möchten, um den Konfigurationsimport während der Modulentwicklung zu beschleunigen (und Sie sich nicht für das Zusammenführen mit Client-Updates interessieren), Es reicht aus, diese Suite nur in Ihrer lokalen (Entwicklungs-) Umgebung zu installieren und zu aktivieren (vorausgesetzt, Ihr Modul wird nach der Fertigstellung in höhere Umgebungen versetzt und Sie verwenden die D8-Kernkonfigurationsverwaltung, um die Konfiguration in höheren Umgebungen zu veröffentlichen).

1
Mirsoft