Score:1

Enum class not found when trying to use it in settings.php

cn flag

I defined an enum in a custom module:

namespace Drupal\my_module\Enum;

enum BuildType: string {
  case Apple = 'apple_build';
  case Orange = 'orange_build';
}

And I want to use it in settings.php to change the config directory of the site:

settings.php:

$build_type = BuildType::from(getenv('build_type'));

$settings['config_sync_directory'] = dirname(DRUPAL_ROOT) . '/config/base_' . $build_type->value;

$settings['custom_translations_directory'] = dirname(DRUPAL_ROOT) . '/translations/' . $build_type->value;

However, when I do this, I get a namespace error:

Error: Class "Drupal\my_module\Enum\BuildType" not found in /var/www/html/web/sites/default/settings.custom.php on line 14 #0 /var/www/html/web/sites/default/settings.php(32): include()

How can I correctly namespace my enum for use in settings.php?

Alfred Armstrong avatar
cn flag
Is your module enabled? Also please post the "use" statement you included.
apaderno avatar
us flag
Since the error is about `Drupal\my_module\Enum\BuildType`, it must be `use Drupal\my_module\Enum\BuildType;`.
Score:2
us flag

The settings.php file is loaded from DrupalKernel::initializeSettings(), which is called from DrupalKernel::handle() before DrupalKernel::boot().

See the code in Settings::initialize(), called by DrupalKernel::initializeSettings().

if (is_readable($app_root . '/' . $site_path . '/settings.php')) {
  require $app_root . '/' . $site_path . '/settings.php';
}

This means that when the code in settings.php is executed, the dependency injection container hasn't yet initialized, the services aren't yet available, and modules are not loaded. Classes/interfaces/traits defined from contributed/custom modules are not yet available either.

Since the settings.php file does not have access to classes/interfaces a module defines, it should load the file containing the class/interface definition directly or define the class/interface itself. Since the settings.php file is loaded with require, the code to load the class file or declaring the class should be wrapped in an if statement.

if (!class_exists('BuildType')) {
  // Load the class file or declare the class.
}
cn flag
Unfortunately, when I tried defining the enum inside a file included by `settings.php`, I get an error when I run a command such as `drush site-install minimal`: `Cannot declare enum BuildType, because the name is already in use in /var/www/html/web/sites/default/settings.my_module.php`. Simply adding an enum definition to `settings.php` triggers this error.
apaderno avatar
us flag
When you get that error, was the `enum` defined in a single place?
apaderno avatar
us flag
Anyway, since the *settings.php* is loaded with `require`, the class declaration should be put between `if (!class_exists('BuildType') {` and `}`, in the *settings.php* file.
Score:0
cn flag

Here's the final code based on apaderno's answer:

settings.php:

if (!class_exists('BuildType') {
  enum BuildType: string {
    case Apple = 'apple_build';
    case Orange = 'orange_build';
  }
}

$build_type = BuildType::from(getenv('build_type'));

$settings['config_sync_directory'] = dirname(DRUPAL_ROOT) . '/config/base_' . $build_type->value;

$settings['custom_translations_directory'] = dirname(DRUPAL_ROOT) . '/translations/' . $build_type->value;
I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.