5

I want to create a field with hook_update in my module. I have the following code that creates the configuration for a field_link field:

$module_path = drupal_get_path('module', 'my_module');
$configs['field.field.paragraph.image.field_link'] = $module_path . '/config/install/field.field.paragraph.image.field_link.yml';
$configs['field.storage.paragraph.field_link'] = $module_path . '/config/install/field.storage.paragraph.field_link.yml';

foreach ($configs as $name => $config_path) {
  $data = Yaml::parse($config_path);
  $config = \Drupal::configFactory()->getEditable($name);
  $config->setData($data)->save(TRUE);
}

As far as configuration it seems to be working correctly. When I try to create a node it all displays as it should. But if you save, you get an error that the table doesn't exist. Perhaps I have to use the ConfigInstaller class. Anyone know how to have the table get created?

4 Answers 4

3

Thanks @Berdir. I was able to create the field with FieldConfig & FieldStorageConfig classes.

$module_path = drupal_get_path('module', 'my_module');

$yml = Yaml::parse(file_get_contents($module_path . '/config/install/field.storage.paragraph.field_link.yml'));
if (!FieldStorageConfig::loadByName($yml['entity_type'], $yml['field_name'])) {
  FieldStorageConfig::create($yml)->save();
}
$yml = Yaml::parse(file_get_contents($module_path . '/config/install/field.field.paragraph.image.field_link.yml'));
if (!FieldConfig::loadByName($yml['entity_type'], $yml['bundle'], $yml['field_name'])) {
  FieldConfig::create($yml)->save();
}
1

Don't use the low-level config, that doesn't trigger the necessary API calls.

Use FieldConfig::create() and FieldStorageConfig::create()

4
  • The thing is that my module has the config in the install directory. Not sure if FieldConfig can be used by reading from the yml config files.
    – albertski
    Feb 6, 2017 at 20:20
  • The actual logic that core uses in \Drupal\Core\Config\ConfigImporter::importInvokeOwner. It is a bit more complicated to support certain use cases like list fields that transform their structure a bit, but for most field types it should work. You can also convert it into a PHP array and then pass it to ::create().
    – Berdir
    Feb 6, 2017 at 22:51
  • @Berdir How can you transform the YAML structure for a list field? I get an error when trying to create field storage using a yaml file for a list_string field.
    – Tim
    Sep 12, 2017 at 15:14
  • @Berdir Think I answered my own question.
    – Tim
    Sep 12, 2017 at 16:00
0

Rather than use the Yaml class directly, it's better to use FieldStorage. Storage settings may need to be transformed, depending on the field type.

$config_path = drupal_get_path('module', 'my_module') . '/config/install';
$storage = new FileStorage($config_path);

// Note: .yml extension not needed.
$data = $source->read('field.storage.paragraph.field_link');

if (!FieldStorageConfig::loadByName($data['entity_type'], $data['field_name'])) {
  // Transform storage settings, if required.
  $field_type_manager = \Drupal::service('plugin.manager.field.field_type');
  $class = $field_type_manager->getPluginClass($data['type']);
  $data['settings'] = $class::storageSettingsFromConfigData($data['settings']);

  FieldStorageConfig::create($data)->save();
}
0

In my case I already had the configuration in my sync folder

  $config_storage = new FileStorage('../config/sync');
  foreach ([
    'field.storage.paragraph.field_button_style',
    'field.field.paragraph.quick_donate_widget.field_button_style',
  ] as $config_name) {
    $entity_type = \Drupal::service('config.manager')->getEntityTypeIdByName($config_name);
    $storage = \Drupal::entityTypeManager()->getStorage($entity_type);
    $config_record = $config_storage->read($config_name);

    /** @var \Drupal\Core\Config\Entity\ConfigEntityStorageInterface $storage */
    $entity = $storage->createFromStorageRecord($config_record);
    if ($storage->load($entity->id())) {
      continue;
    }
    $entity->save();

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.