Business

Programmatically Importing Drupal 8 Field Configurations

Sometimes during development, a chicken and egg situation happens when business logic intersects with Drupal's mechanisms. For instance, a custom module, client_business_logic, is built to handle some unique, abstract bit of logic which depends on a taxonomy vocabulary


Filed under:

This article is one of Metal Toad's Top 20 Drupal Tips. Enjoy!

Sometimes during development, a chicken and egg situation happens when business logic intersects with Drupal's mechanisms. For instance, a custom module, client_business_logic, is built to handle some unique, abstract bit of logic which depends on a taxonomy vocabulary that has fields added to it. Now, all of the entity and field structures can be handled via Drupal 8's Configuration API, but since the client will install this site a number of times, we would like to provide some baseline taxonomy terms at the start. If the field's configuration has not been imported before the module is enabled, then that field's data will not be saved.

To solve this, I attempted to import the configurations during client_business_logic_install() similar to how I would handle them in Drupal 7 with Features. There are examples found here and here describe programmatically importing configurations from yaml files, but when I tried their approach, I received an error: Base table or view not found. Which seemed to indicate Drupal is detecting field configuration and so it's assuming the database table has been created. Sure enough, the configuration write does not perform changes to the database.

Then, I came across this StackOverflow solution for programmatically building fields. The original post used hard-coded arrays that appeared to be the same configuration structures stored in yaml, just missing extras like UUIDs, and the configurations that I was trying import were for Drupal entities, not just arbitrary settings. So, I tried combining the two approaches and it worked without any UUID or renaming confusion in subsequent configuration imports and exports. This can also work within update scripts, hook_update_N().

drupal/modules/custom/client_business_logic/client_business_logic.install
<?php
 
use Drupal\taxonomy\Entity\Term;
use Drupal\Core\Config\FileStorage;
 
/**
 * Implement hook_install().
 */
function client_business_logic_install() {
  // Obtain configuration from yaml files
  $config_path = 'path/to/config';
  $source      = new FileStorage($config_path);
 
  // Obtain the storage manager for vocabularies
  // Create a new vocabulary from the yaml configuration and save
  \Drupal::entityManager()->getStorage('taxonomy_vocabulary')
    ->create($source->read('taxonomy.vocabulary.business_logic_vocab'))
    ->save();
 
  // Obtain the storage manager for field storage bases
  // Create a new field from the yaml configuration and save
  \Drupal::entityManager()->getStorage('field_storage_config')
    ->create($source->read('field.storage.taxonomy_term.field_machine_name'))
    ->save();
 
  // Obtain the storage manager for field instances
  // Create a new field instance from the yaml configuration and save
  \Drupal::entityManager()->getStorage('field_config')
    ->create($source->read('field.field.taxonomy_term.business_logic_vocab.field_machine_name'))
    ->save();
 
  // Create taxonomy terms
  $terms = [
    'Default' => [
      'field_machine_name' => [
        0 => ['value' => 'default'],
      ],
    ],
    ...
  ];
  $weight = 0;
  foreach ($terms as $name => $fields) {
    Term::create([
      'name'   => $name,
      'weight' => $weight++,
      'vid'    => 'business_logic_vocab',
    ] + $fields)->save();
  }
}

Similar posts

Get notified on new marketing insights

Be the first to know about new B2B SaaS Marketing insights to build or refine your marketing function with the tools and knowledge of today’s industry.