我有一个自定义模块,该模块安装一组特定的配置-所有这些配置都存储在config/install
文件夹中,这意味着它们是在安装模块时安装的。
该配置包括内容类型,段落,查看模式,表单模式,字段存储以及附加到内容类型和段落的字段等。该想法是使用此模块安装“功能”(博客)并在多个站点上使用它,并在我们向此功能添加更多内容时提供更新和扩展。
自从初始安装以来,您无法通过config/install
文件夹添加更多配置,我一直在尝试找到一种通过更新挂钩导入其他配置文件的方法,该方法有效:>
<?php
use \Symfony\Component\Yaml\Yaml;
/**
* Installs the file upload element
*/
function MODULE_NAME_update_8002() {
// Is the flaw with this the fact that the order of loading configurations now
// matters and is a little bit more difficult to deal with?
// NOTE: YES. If, for example, you comment out the installing of the
// field_storage for the field_cb_file, but try to add the field_cb_file to
// the paragraph type, the update is successful and no errors are thrown.
// This is basically me trying to re-create the drupal configuration management
// system, without the dependency checks, etc. What is the PROPER way of
// importing additional configuration from a module through an update?
// FIXME:
$configs_to_install = [
'paragraphs.paragraphs_type.cbsf_file_download',
'field.storage.paragraph.field_cb_file',
'field.field.paragraph.cbsf_file_download.field_cb_file',
'field.field.paragraph.cbsf_file_download.field_cb_heading',
'field.field.paragraph.cbsf_file_download.field_cb_icon',
'field.field.paragraph.cbsf_file_download.field_cb_text',
'core.entity_form_display.paragraph.cbsf_file_download.default',
'core.entity_view_display.paragraph.cbsf_file_download.default',
];
foreach ($configs_to_install as $config_to_install) {
$path = drupal_get_path('module', 'MODULE_NAME') . '/config/update_8002/' . $config_to_install . '.yml';
$content = file_get_contents($path);
$parsed_yml = Yaml::parse($content);
$active_storage = \Drupal::service('config.storage');
$active_storage->write($config_to_install, $parsed_yml);
}
}
但是,此方法存在缺陷,因为它意味着如果彼此依赖,则必须以正确的顺序对配置文件进行排序,并且不会检查配置文件中存在的任何依赖关系。
是否有一种方法可以利用配置管理正确地导入配置,以同样的方式“遍历文件”?还是指向包含所有配置文件的文件夹并安装它们?
编辑:此方法还有其他问题-即使您已经按照相关性正确订购了文件,也不会创建数据库表。配置只是按原样“写入”,并且Drupal的其他部分似乎没有意识到已经创建了新实体,因此如果您要通过Drupal GUI创建实体,它们将无法运行否则会运行的任何功能。 。 绝对不是推荐的传输更复杂配置的方法。
答案 0 :(得分:1)
我将这一步骤进一步推进-有一种方法可以使用EntityTypeManager类创建/更新配置。
2个链接在很大程度上帮助了我:
https://drupal.stackexchange.com/questions/164713/how-do-i-update-the-configuration-of-a-module
pwolanins底部的答案提供了一个功能,该功能可以更新配置(如果存在)或直接创建配置。
https://www.metaltoad.com/blog/programmatically-importing-drupal-8-field-configurations
此页面上的代码使您可以更清楚地了解正在发生的事情-对于要安装的每个配置,请通过各自的存储管理器运行YML文件,然后创建适当的实体配置,该配置将创建所有所需的数据库表。
我最终要做的是:
使用了pwolanins代码的略微修改版本,并创建了通用的配置更新程序功能-
function _update_or_install_config( String $prefix, String $update_id, String $module) {
$updated = [];
$created = [];
/** @var \Drupal\Core\Config\ConfigManagerInterface $config_manager */
$config_manager = \Drupal::service('config.manager');
$files = glob(drupal_get_path('module', $module) . '/config/update_' . $update_id. '/' . $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);
}
$type = $config_manager->getEntityTypeIdByName(basename($file));
$entity_manager = $config_manager->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 [
'udpated' => $updated,
'created' => $created,
];
}
我将所有yml
文件放在文件夹config/update_8002
中,然后利用此函数在hook_update_N函数中循环配置文件:
function MODULE_NAME_update_8002() {
$configs_to_install = [
'paragraphs.paragraphs_type.cbsf_file_download',
'core.entity_form_display.paragraph.cbsf_file_download.default',
'core.entity_view_display.paragraph.cbsf_file_download.default',
'field.storage.paragraph.field_cb_file',
'field.field.paragraph.cbsf_file_download.field_cb_file',
'field.field.paragraph.cbsf_file_download.field_cb_heading',
'field.field.paragraph.cbsf_file_download.field_cb_icon',
'field.field.paragraph.cbsf_file_download.field_cb_text',
];
foreach ($configs_to_install as $config_to_install) {
_update_or_install_config('paragraphs.paragraphs_type', '8002', 'MODULE_NAME');
_update_or_install_config('field.storage.paragraph', '8002', 'MODULE_NAME');
_update_or_install_config('field.field.paragraph', '8002', 'MODULE_NAME');
_update_or_install_config('core.entity_view_display.paragraph', '8002', 'MODULE_NAME');
_update_or_install_config('core.entity_form_display.paragraph', '8002', 'MODULE_NAME');
}
}
请注意,_update_or_install_config
函数遍历文件夹中与特定实体类型管理器匹配的所有配置-因此,您应该只在函数中包括前缀,以及所有导入配置的YML文件将会包含相同的类型。