Làm cách nào để cập nhật cấu hình của mô-đun?


33

Tôi đang xây dựng một mô-đun tùy chỉnh trong Drupal 8. Nó bao gồm một số tệp cấu hình YAML.

Khi tôi phát triển, tôi cần thay đổi và thêm vào cấu hình, ví dụ để thêm một trường khác vào thực thể tùy chỉnh của mình.

Hiện tại, cách duy nhất tôi tìm thấy để khiến Drupal nhận thấy các thay đổi là gỡ cài đặt mô-đun và cài đặt lại.

Có cách nào để Drupal kiểm tra xem các tệp cấu hình được cung cấp bởi các mô-đun có giống với cấu hình hoạt động không và nếu không, hãy cập nhật cấu hình hoạt động? Cập nhật mô-đun được xử lý như thế nào? Trong D7 hook_update_Nsẽ được sử dụng để thêm các trường bằng PHP, nhưng có vẻ như điều này sẽ được xử lý bởi CM trong D8?

Những điều tôi đã thử sau khi cập nhật các tệp yml trong mô-đun:

  1. drush cr, cấu hình đồng bộ.

  2. sao chép thủ công tất cả các tệp cấu hình được cập nhật vào sites/default/files/config_XXX/staging/- nhưng điều này gây ra lỗi này "Không thể nhập cấu hình theo giai đoạn, vì nó bắt nguồn từ một trang web khác với trang web này. Bạn chỉ có thể đồng bộ hóa cấu hình giữa các phiên bản được nhân bản của trang web này." .

  3. nhập thủ công từng tệp một bằng trình quản lý cấu hình. Điều này hoạt động, nhưng rõ ràng phải có một cách tự động hơn.

  4. [EDIT] sử dụng mô-đun config_update theo cách thủ công để kiểm tra các thay đổi và 'hoàn nguyên' về cấu hình của mô-đun. Một lần nữa, đây là thủ công.

EDIT: Từ Quản lý cấu hình - làm và không nên

KHÔNG

Cố gắng thay đổi cấu hình hoạt động trên trang web của bạn bằng cách thay đổi các tệp trong thư mục config / install của mô-đun. Điều này sẽ KHÔNG hoạt động vì Drupal sẽ chỉ đọc từ thư mục đó khi mô-đun được cài đặt.

... nhưng những thay đổi sẽ xảy ra, trừ khi các mô-đun bị ràng buộc với bất kỳ cấu hình nào họ cần trong lần phát hành đầu tiên và có thể không bao giờ cập nhật hoặc thêm cấu hình.

Cảm ơn trước.


Tôi nghĩ rằng một cái gì đó rất giống đã được hỏi trước đây (không thể tìm thấy ngay bây giờ) và tôi nghĩ rằng câu trả lời là cấu hình mặc định chỉ được tư vấn khi cài đặt, vì vậy cài đặt lại là cách để đi. Đừng báo giá cho tôi :)
Clive

1
'K, nhưng làm thế nào một mô-đun sẽ được cập nhật? Các mô-đun được phép nhận cập nhật trong D8, phải không ;-)? Phải có một cách (a la config_update) cho các mô-đun để nói "Drupal! Bây giờ tôi yêu cầu cấu hình bổ sung này, hãy xem và hợp nhất nó trong xin vui lòng."
artfulrobot

Trình quản lý cập nhật cấu hình thực hiện công việc, nhưng tôi đồng ý rằng có vẻ như cần có một cách riêng để thực hiện việc này. Một cái gì đó trong hook_update_Ntôi giả định, nhưng tôi không chắc chắn điều gì
Clive

2
Ồ, tôi nghĩ rằng câu trả lời có thể là "bạn không thể"! Không bao giờ thấy rằng đến! Quay lại hook_update_N. Bài viết tuyệt vời về Drupal 8 cho các trang web nhỏ (và phần 2 ). Trong D8 "các trang web sở hữu cấu hình của chúng, không phải mô-đun" .
artfulrobot

Tôi muốn thêm rằng một trường hợp sử dụng tuyệt vời cho việc này là một thiết lập nhiều trang, trong đó bạn muốn chia sẻ các phần cấu hình lớn cụ thể nhưng không phải tất cả và triển khai điều này. Chúng có thể bao gồm các mô-đun tùy chỉnh. Đối với một trang web, nó chỉ đơn giản là một cấu hình xuất / nhập, một multisite sẽ không đơn giản như vậy.
Ambidex

Câu trả lời:


24

Như đã đề cập trong câu hỏi ban đầu và nhận xét tiếp theo, có nhiều mô-đun đóng góp và phương pháp thủ công để thực hiện việc này.

Để làm điều đó tự động, hoặc theo cách tùy chỉnh, tôi nghĩ hook_update_N()có lẽ vẫn là lựa chọn khả thi nhất.

Chẳng hạn, đây là một ví dụ từ Head 2 Head để cập nhật system.siteđể đặt default_langcode:

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

Bạn cũng có thể đọc trong cấu hình (chỉ được khuyến nghị để thêm cấu hình mới, không nhất thiết phải cập nhật hoặc ghi đè cấu hình có thể đã được tùy chỉnh):

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

đâu $pathlà đường dẫn tuyệt đối đến my_config.foo.ymltập tin.


1
Khi tôi theo cách tiếp cận thứ hai, cấu hình được ghi vào Drupal nhưng không nhận được UUID ngay cả khi tôi xuất nó sang thư mục cấu hình. Điều này dẫn tôi đến một vấn đề mà tôi đã thử điều này với Chế độ xem tùy chỉnh. Trang tổng quan Lượt xem trả về cho tôi một lỗi nghiêm trọng do uuid cho thực thể Cấu hình không khả dụng.
Sebastian

9

Khi tôi cũng trả lời câu hỏi này nhưng không thực sự tìm thấy câu trả lời chính xác cho tình huống của mình ở đây, tôi muốn thêm một câu trả lời khác.

Xin lưu ý: Chống mẫu trước!

Ca sử dụng

Khi chúng tôi phát triển dự án, chúng tôi liên tục cập nhật môi trường thử nghiệm / chấp nhận với các cập nhật cấu hình mới. Ví dụ như một mô-đun Tin tức hư cấu đơn giản, chúng tôi muốn thêm một loại nội dung vào mô-đun và triển khai mô-đun này vào môi trường chấp nhận của chúng tôi. Sau khi xem xét, chúng tôi đã kết luận có một vài trường bị thiếu và các nội dung liên quan đến cấu hình khác. Vì chúng tôi biết môi trường chấp nhận không được cập nhật trong cấu hình, chúng tôi thực sự chỉ muốn tải lại toàn bộ cấu hình từ mô-đun trong khi thêm chức năng mới và không bị làm phiền bằng cách nhập mọi .ymltệp đã thay đổi .

Chúng tôi chỉ cần cấu hình của chúng tôi trong các mô-đun khi chúng tôi đang phát triển nhiều trang. Đối với các trang web đơn lẻ, chúng tôi chủ yếu chỉ sử dụng cấu hình trang web xuất khẩu trong đó bước tiếp theo là không cần thiết.

Reimport cấu hình hoàn toàn (chống mẫu!)

Chúng tôi thấy rằng bằng cách sử dụng dịch vụ ConfigInstaller , chúng tôi có thể nhập lại cấu hình hoàn chỉnh từ một mô-đun cụ thể.

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

Sử dụng cẩn thận!

Tôi muốn thêm rằng điều này sẽ ghi đè lên bất kỳ nội dung hoạt động nào đã bị thay đổi trong môi trường. Vì vậy, chỉ sử dụng giải pháp này khi bạn chắc chắn an toàn để ghi đè lên cấu hình hoạt động. Chúng tôi sẽ không bao giờ sử dụng điều này trên môi trường sản xuất và sẽ chỉ áp dụng trong giai đoạn đầu phát triển.

Trước tiên hãy thử giải pháp của @ jhedstrom trước khi bạn bắt đầu xem xét giải pháp này.


9

Tôi đã tìm thấy Gist này trên GitHub, nó hoàn nguyên / tải lại cấu hình của mô-đun đã cho bằng cách sử dụng drush:

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

2

Dựa trên nhận xét của tôi: Làm cách nào để cập nhật cấu hình của mô-đun?

Khi tôi theo cách tiếp cận thứ hai, cấu hình được ghi vào Drupal nhưng không nhận được UUID ngay cả khi tôi xuất nó sang thư mục cấu hình. Điều này dẫn tôi đến một vấn đề mà tôi đã thử điều này với Chế độ xem tùy chỉnh. Trang tổng quan Lượt xem trả về cho tôi một lỗi nghiêm trọng do uuid cho thực thể Cấu hình không khả dụng.

Tôi đã tạo ra một hàm nhỏ giúp tôi với điều đó, ở đây mã ví dụ của tôi:

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

Câu trả lời ở trên (nhập lại đầy đủ) cũng hoạt động cho trường hợp sử dụng của tôi, nhưng trước tiên tôi đã dành một chút thời gian để xem xét việc nhập lại có chọn lọc hơn. Đây là mã mà tôi có dường như hoạt động như một bản cập nhật và được dựa trên mã trong mô-đun 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

Đồng bộ hóa cấu hìnhMô-đun giúp giải quyết vấn đề này một cách tốt đẹp. Bộ mô-đun gồm 7 mô-đun này có vẻ hơi quá mức chỉ dành cho trường hợp này (mục đích của nó chủ yếu là hợp nhất một cách an toàn trong các bản cập nhật mà không cần ghi đè tùy chỉnh), nhưng vì khái niệm của nó, nó cũng cho phép theo dõi và nhập các thay đổi cấu hình từ / cài đặt mô-đun và / thư mục tùy chọn nhanh chóng.

Về cơ bản, bạn có thể kiểm tra nó như sau:

  • tạo và kích hoạt mô-đun tùy chỉnh trên môi trường cục bộ của bạn với một số mục cấu hình "mặc định" được đặt trong thư mục / config / install như bình thường
  • cài đặt và kích hoạt mô-đun config_sync và tất cả các mô-đun phụ thuộc của nó
  • thực hiện một số chỉnh sửa trong mục cấu hình mô-đun của bạn bên trong thư mục / config / install
  • truy cập / admin / config / Development / configure / distro. Bạn sẽ thấy thay đổi của mình và có tùy chọn để nhập nó vào cấu hình hoạt động (Chế độ hợp nhất nhằm duy trì các thay đổi của máy khách, Đặt lại chế độ bắt buộc nhập) - trong quá trình phát triển, tôi sẽ chủ yếu sử dụng chế độ Đặt lại, nhưng chế độ hợp nhất cũng hoạt động trừ khi bạn đã thực hiện bất kỳ thay đổi thủ công trong cùng một cấu hình song song

Lưu ý: nếu bạn chỉ muốn sử dụng config_sync để tăng tốc nhập cấu hình trong quá trình phát triển mô-đun (và bạn không quan tâm đến việc hợp nhất với các bản cập nhật máy khách), thì chỉ cần cài đặt và kích hoạt bộ này trên môi trường (phát triển) cục bộ của bạn ( giả sử mô-đun của bạn sẽ chuyển đến các môi trường cao hơn sau khi hoàn tất và bạn sử dụng quản lý cấu hình lõi D8 để đăng cấu hình của nó lên các môi trường cao hơn).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.