ฉันจะอัพเดตการกำหนดค่าของโมดูลได้อย่างไร?


33

ฉันกำลังสร้างโมดูลที่กำหนดเองใน Drupal 8 ซึ่งมีไฟล์กำหนดค่า YAML บางไฟล์

ขณะที่ฉันพัฒนาฉันต้องเปลี่ยนและเพิ่มการกำหนดค่าเช่นเพื่อเพิ่มฟิลด์อื่นลงในเอนทิตีที่กำหนดเองของฉัน

ในปัจจุบันวิธีเดียวที่ฉันได้รับ Drupal สังเกตเห็นการเปลี่ยนแปลงคือการถอนการติดตั้งโมดูลและติดตั้งใหม่

มีวิธีใดที่จะทำให้ Drupal ตรวจสอบว่าไฟล์ config ที่โมดูลจัดเตรียมไว้นั้นเหมือนกับการกำหนดค่าที่ใช้งานอยู่และถ้าไม่ให้อัพเดทการตั้งค่าที่ใช้งานอยู่ มีการจัดการปรับปรุงโมดูลอย่างไร ใน D7 hook_update_Nจะถูกใช้เพื่อเพิ่มฟิลด์โดยใช้ PHP แต่ดูเหมือนว่า CM นี้จะได้รับการจัดการโดย D8?

สิ่งที่ฉันได้ลองหลังจากอัปเดตไฟล์ yml ในโมดูล:

  1. drush cr, กำหนดค่าการซิงค์

  2. การคัดลอกไฟล์กำหนดค่าที่อัปเดตด้วยตัวเองทั้งหมดsites/default/files/config_XXX/staging/- แต่นี่ทำให้เกิดข้อผิดพลาดนี้"การกำหนดค่าแบบฉากไม่สามารถนำเข้าได้เพราะมันมาจากไซต์อื่นนอกเหนือจากไซต์นี้คุณสามารถซิงโครไนซ์การกำหนดค่าระหว่างอินสแตนซ์ .

  3. การอิมพอร์ตไฟล์ด้วยตนเองทีละคนโดยใช้ตัวจัดการการกำหนดค่า วิธีนี้ใช้ได้ผล แต่จะต้องมีวิธีอัตโนมัติมากกว่า

  4. [แก้ไข] ใช้โมดูลconfig_updateด้วยตนเองเพื่อตรวจสอบการเปลี่ยนแปลงและ 'เปลี่ยนกลับ' เป็นค่ากำหนดของโมดูล นี่เป็นคู่มืออีกครั้ง

แก้ไข:จากการจัดการการกำหนดค่า - สิ่งที่ต้องทำและไม่ควรทำ

DON'TS

ลองเปลี่ยนการกำหนดค่าที่ใช้งานอยู่บนเว็บไซต์ของคุณโดยเปลี่ยนไฟล์ในไดเรกทอรี config / install ของโมดูล สิ่งนี้จะไม่ทำงานเนื่องจาก Drupal จะอ่านจากไดเรกทอรีนั้นเมื่อติดตั้งโมดูลเท่านั้น

... แต่การเปลี่ยนแปลงจะเกิดขึ้นเว้นแต่ว่าโมดูลจะเชื่อมโยงกับสิ่งที่พวกเขาต้องการในการปล่อยครั้งแรกและอาจไม่เคยปรับปรุงหรือเพิ่มการกำหนดค่า

ขอบคุณล่วงหน้า.


ฉันคิดว่าสิ่งที่คล้ายกันมากถูกถามก่อน (ไม่สามารถหาได้ตอนนี้) และฉันคิดว่าคำตอบคือการตั้งค่าเริ่มต้นจะพิจารณาเฉพาะเวลาติดตั้งดังนั้นการติดตั้งใหม่เป็นวิธีที่จะไป อย่าพูดถึงฉัน :)
ไคลฟ์

1
'k แต่โมดูลจะได้รับการปรับปรุงอย่างไร โมดูลได้รับอนุญาตให้รับการอัพเดทใน D8 ใช่มั้ย ;-)? ต้องมีวิธี (a la config_update) สำหรับโมดูลที่จะพูดว่า "Drupal! ตอนนี้ฉันต้องการการตั้งค่าพิเศษนี้ลองดูและรวมมันเข้าด้วยกัน"
artfulrobot

เครื่องมือจัดการการกำหนดค่าอัปเดตทำงานได้ แต่ฉันเห็นด้วยว่ารู้สึกว่าควรมีวิธีดั้งเดิมในการทำเช่นนี้ มีบางอย่างที่hook_update_Nฉันคิด แต่ฉันไม่แน่ใจว่าอะไร
ไคลฟ์

2
ว้าวฉันคิดว่าคำตอบอาจจบลงด้วยการเป็น "คุณทำไม่ได้"! ไม่เคยเห็นว่ามา! hook_update_Nกลับไป บทความที่ยอดเยี่ยมเกี่ยวกับDrupal 8 สำหรับไซต์ขนาดเล็ก (และตอนที่ 2 ) ใน D8 "เว็บไซต์ที่เป็นเจ้าของการกำหนดค่าของพวกเขาไม่ Modules"
artfulrobot

ฉันต้องการเพิ่มว่ากรณีการใช้งานที่ยอดเยี่ยมสำหรับกรณีนี้คือการตั้งค่าแบบหลายไซต์ซึ่งคุณต้องการแบ่งปันการกำหนดค่าขนาดใหญ่เฉพาะส่วน แต่ไม่ใช่ทั้งหมดและปรับใช้สิ่งนี้ สิ่งเหล่านี้อาจรวมถึงโมดูลที่กำหนดเอง สำหรับไซต์เดียวมันจะเป็นการส่งออก / นำเข้าการกำหนดค่าหลายไซต์จะไม่ง่ายขนาดนั้น
Ambidex

คำตอบ:


24

ดังที่ได้กล่าวไว้ในคำถามเดิมและความคิดเห็นที่ตามมามีโมดูล contrib และวิธีการด้วยตนเองที่หลากหลายเพื่อให้บรรลุสิ่งนี้

เมื่อต้องการทำโดยอัตโนมัติหรือในแบบที่กำหนดเองฉันคิดว่าhook_update_N()ยังคงเป็นตัวเลือกที่เหมาะสมที่สุด

ตัวอย่างเช่นนี่เป็นตัวอย่างจากHead 2 Head ที่จะอัปเดตsystem.siteเพื่อตั้งค่าdefault_langcode:

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

คุณยังสามารถอ่านการกำหนดค่า (แนะนำสำหรับการเพิ่มการกำหนดค่าใหม่เท่านั้นไม่จำเป็นต้องอัปเดตหรือแทนที่การกำหนดค่าที่อาจปรับแต่ง):

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

โดยที่$pathเป็นพา ธ สัมบูรณ์ไปยังmy_config.foo.ymlไฟล์


1
เมื่อฉันทำตามวิธีที่สองการตั้งค่าจะถูกเขียนไปยัง Drupal แต่ไม่ได้รับ UUID แม้ว่าฉันจะส่งออกไปยังไดเรกทอรีการตั้งค่า สิ่งนี้นำฉันไปสู่ปัญหาที่ฉันลองทำด้วยมุมมองที่กำหนดเอง หน้ามุมมองภาพรวมส่งคืนข้อผิดพลาดร้ายแรงให้ฉันเนื่องจาก uuid สำหรับเอนทิตีกำหนดค่าไม่พร้อมใช้งาน
เซบาสเตียน

9

เมื่อฉันลงจอดในคำถามนี้ แต่ไม่พบคำตอบที่ถูกต้องสำหรับสถานการณ์ของฉันที่นี่ฉันต้องการเพิ่มคำตอบอื่น

โปรดทราบ: Anti-pattern ล่วงหน้า!

ใช้กรณี

เมื่อเราพัฒนาโครงการเราจะปรับปรุงสภาพแวดล้อมการทดสอบ / การยอมรับของเราอย่างต่อเนื่องด้วยการอัพเดทการกำหนดค่าใหม่ ยกตัวอย่างเช่น News-module แบบสวมง่ายเราต้องการเพิ่มประเภทเนื้อหาลงในโมดูลและปรับใช้กับสภาพแวดล้อมการยอมรับของเรา หลังจากตรวจทานเราได้สรุปว่ามีบางฟิลด์ที่ขาดหายไปและสิ่งอื่น ๆ ที่เกี่ยวข้องกับการกำหนดค่า เนื่องจากเราทราบว่าสภาพแวดล้อมการยอมรับไม่ได้รับการอัปเดตในการตั้งค่าเราจึงต้องการโหลดการกำหนดค่าทั้งหมดจากโมดูลในขณะที่เพิ่มฟังก์ชั่นใหม่และไม่ต้องกังวลกับการนำเข้า.ymlไฟล์ที่เปลี่ยนแปลงทั้งหมด

เราต้องการการกำหนดค่าของเราในโมดูลเมื่อเราพัฒนาหลายไซต์เท่านั้น สำหรับไซต์เดียวเราส่วนใหญ่จะใช้การกำหนดค่าไซต์ที่ส่งออกซึ่งขั้นตอนต่อไปไม่จำเป็น

นำเข้าการกำหนดค่าใหม่ทั้งหมด (แบบป้องกัน!)

เราพบว่าการใช้บริการConfigInstallerเราสามารถนำเข้าการกำหนดค่าทั้งหมดอีกครั้งจากโมดูลเฉพาะ

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

ใช้ด้วยความระมัดระวัง!

ฉันต้องการเพิ่มว่าสิ่งนี้จะเขียนทับเนื้อหาใด ๆ ที่ใช้งานซึ่งมีการเปลี่ยนแปลงภายในสภาพแวดล้อม ดังนั้นให้ใช้โซลูชันนี้เฉพาะเมื่อคุณแน่ใจว่าปลอดภัยที่จะเขียนทับการตั้งค่าที่ใช้งานอยู่ เราจะไม่ใช้สิ่งนี้ในสภาพแวดล้อมการผลิตและจะนำไปใช้ในการพัฒนาเท่านั้น

ก่อนอื่นลองใช้วิธีการแก้ปัญหาของ @jhedstrom ก่อนที่จะเริ่มพิจารณาสิ่งนี้


9

ฉันได้พบGist นี้ใน GitHub ซึ่งย้อนกลับ / โหลดซ้ำได้รับการกำหนดค่าโมดูลโดยใช้ drush:

drush cim -y --partial --source=modules/path/to/module/config/install/

2

จากความคิดเห็นของฉัน: ฉันจะอัปเดตการกำหนดค่าของโมดูลได้อย่างไร

เมื่อฉันทำตามวิธีที่สองการตั้งค่าจะถูกเขียนไปยัง Drupal แต่ไม่ได้รับ UUID แม้ว่าฉันจะส่งออกไปยังไดเรกทอรีการตั้งค่า สิ่งนี้นำฉันไปสู่ปัญหาที่ฉันลองทำด้วยมุมมองที่กำหนดเอง หน้ามุมมองภาพรวมส่งคืนข้อผิดพลาดร้ายแรงให้ฉันเนื่องจาก uuid สำหรับเอนทิตีกำหนดค่าไม่พร้อมใช้งาน

ฉันได้สร้างฟังก์ชั่นเล็ก ๆ ที่ช่วยให้ฉันด้วยที่นี่รหัสตัวอย่างของฉัน:

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.';
}

1

คำตอบข้างต้น (นำเข้าซ้ำทั้งหมด) ยังใช้กับกรณีการใช้งานของฉันด้วย แต่ก่อนอื่นฉันใช้เวลาเล็กน้อยในขณะที่มองหาการนำเข้าซ้ำที่เลือกมากขึ้น นี่คือรหัสที่ฉันมีซึ่งดูเหมือนว่าจะทำงานเป็นเบ็ดการอัพเดทและขึ้นอยู่กับรหัสในโมดูล config_update:

/**
 * 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

โมดูลSynchronizer ของการกำหนดค่าช่วยในการแก้ปัญหานี้ในทางที่ดี ชุดโมดูล 7 โมดูลนี้ดูเหมือนว่าจะ overkill เพียงเล็กน้อยสำหรับกรณีนี้ (ความตั้งใจส่วนใหญ่จะรวมในการปรับปรุงอย่างปลอดภัยโดยไม่ต้องเขียนทับการปรับแต่ง) แต่เนื่องจากแนวคิดของมันมันยังช่วยให้สามารถติดตามและนำเข้าการเปลี่ยนแปลงการกำหนดค่าจากโมดูล / ติดตั้งและ / โฟลเดอร์เสริมได้อย่างรวดเร็ว

โดยทั่วไปคุณสามารถทดสอบได้ดังต่อไปนี้:

  • สร้างและเปิดใช้งานโมดูลที่กำหนดเองของคุณในสภาพแวดล้อมท้องถิ่นของคุณด้วยรายการการกำหนดค่า "เริ่มต้น" บางรายการที่วางไว้ใน / config / ติดตั้งโฟลเดอร์ตามปกติ
  • ติดตั้งและเปิดใช้งานโมดูล config_sync และโมดูลที่ขึ้นต่อกันทั้งหมด
  • ทำการแก้ไขบางอย่างในรายการกำหนดค่าโมดูลของคุณในโฟลเดอร์ / config / install
  • เข้าถึง / ผู้ดูแลระบบ / กำหนดค่า / พัฒนา / กำหนดค่า / distro คุณควรเห็นการเปลี่ยนแปลงของคุณและมีตัวเลือกที่จะนำเข้าสู่การกำหนดค่าที่ใช้งานอยู่ (โหมดการผสานมีไว้เพื่อรักษาการเปลี่ยนแปลงไคลเอนต์, การรีเซ็ตกำลังบังคับโหมดการนำเข้า) - ระหว่างการพัฒนาฉันส่วนใหญ่จะใช้โหมดการตั้งค่าใหม่ ทำการเปลี่ยนแปลงด้วยตนเองในการกำหนดค่าเดียวกันในแบบคู่ขนาน

หมายเหตุ: หากคุณเพียงต้องการที่จะใช้ config_sync เพื่อเร่งนำเข้าการตั้งค่าในระหว่างการพัฒนาโมดูล (และคุณไม่สนใจเกี่ยวกับการควบรวมกิจการในที่มีการปรับปรุงไคลเอนต์) ก็พอที่จะมีชุดนี้ติดตั้งและเปิดใช้งาน (การพัฒนา) สภาพแวดล้อมในท้องถิ่นของคุณเท่านั้น ( สมมติว่าโมดูลของคุณจะไปสู่สภาพแวดล้อมที่สูงขึ้นหลังจากทำการสรุปและคุณใช้การจัดการการกำหนดค่าแกน D8 เพื่อโพสต์การกำหนดค่าไปยังสภาพแวดล้อมที่สูงขึ้น)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.