It's fairly common to split up settings and configuration between multiple files, and to include these files in settings.php.

However, it appears that settings.php is read multiple times during site installs, leading to unexpected behavior if you use include_once or require_once (instead of include or require) in settings.php. For instance, if you set $config_directories in a separate file and call it with require_once, the site install task will not be able to read it, and a random config_directory value will be written to settings.php.

I believe the root cause is that settings.php is being included by the core install / bootstrap tasks multiple times. The first time, $config_directories is not defined as a global prior to the file being included, so this variable is simply lost. Only on a later include (such as in Drupal\Core\Site\Settings::Initialize()) is $config_directories defined as a global, but by this point it's too late as the variable won't be read again.

I can see two solutions: either document in settings.php that you shouldn't use include_once / require_once, or find all of the functions where settings.php is included by core and ensure that in each case all of the possible variables are defined as globals.

Issue fork drupal-2793259

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

Dane Powell created an issue. See original summary.

cilefen’s picture

Version: 8.1.x-dev » 8.2.x-dev

So, predefining $config_directories works, but moving it to a require_once at the same place, it is ignored. Can you reproduce this on 8.2.x? I ask because there was an issue I can't find at the moment that was similar.

cashwilliams’s picture

Can't reproduce on 8.2.x

danepowell’s picture

Status: Active » Fixed

I can confirm Cash's finding, this seems to no longer be an issue in 8.2.0-beta3.

Closing as fixed, but if you can find the other issue you can mark it as a dupe.

cashwilliams’s picture

Should the fix be back ported to 8.1?

danepowell’s picture

Version: 8.2.x-dev » 8.1.8
Status: Fixed » Active

If it were up to me, yes :) Maybe at least leave this open for future travelers who run across the same issue.

Version: 8.1.8 » 8.1.x-dev

Core issues are now filed against the dev versions where changes will be made. Document the specific release you are using in your issue comment. More information about choosing a version.

Version: 8.1.x-dev » 8.9.x-dev

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Branches prior to 8.8.x are not supported, and Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

Bug reports should be targeted against the 8.9.x-dev branch from now on, and new development or disruptive changes should be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

quietone’s picture

Status: Active » Closed (outdated)
Issue tags: +Bug Smash Initiative

In #4, This was reported fixed in 8.2.0-beta3. It was reopened in #6 in the hope it was backported and to help others. That was over four years and and 8.2.x is no longer supported. It seems sensible to close this as outdated.

fengtan made their first commit to this issue’s fork.

fengtan’s picture

I seem to be able to reproduce this on Drupal 9.1.

Here is what I did:

  1. Make settings.php include another file named settings.included.php (note the use of require_once instead of require)
    $ ls default/
    settings.php
    settings.included.php
    
    $ cat default/settings.php
    <?php
    require_once __DIR__ . '/settings.included.php';
    
    $ cat default/settings.included.php
    <?php
    $settings['hash_salt'] = 'foo';
    $settings['config_sync_directory'] = '../config/sync';
    $settings['trusted_host_patterns'] = ['^localhost$'];
    $databases['default']['default'] = [
      'database' => 'drupal',
      'username' => 'root',
      'password' => 'abcd',
      'prefix' => '',
      'host' => 'mysqld',
      'port' => '3306',
      'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',
      'driver' => 'mysql',
    ];
      
  2. Mount our settings files against a Drupal 9 infrastructure
    $ cat docker-compose.yml 
    version: '3'
    services:
      drupal:
        image: drupal:9-apache
        volumes:
          - ./default:/var/www/html/sites/default
      mysqld:
        image: mysql:5.7
        environment:
          MYSQL_DATABASE: drupal
          MYSQL_ROOT_PASSWORD: abcd
          MYSQL_INITDB_SKIP_TZINFO: 1
    
    $ docker-compose up -d
    
    $ docker-compose exec drupal composer require drush/drush
      
  3. Install site
    $ docker-compose exec drupal /bin/bash
    /opt/drupal# mkdir -p web/sites/default/files
    /opt/drupal# chmod a+w web/sites/default/settings*.php web/sites/default/files
    /opt/drupal# drush -y site-install minimal
      
  4. Expected result: settings.php is left untouched
    /opt/drupal# cat web/sites/default/settings.php
    <?php
    require_once __DIR__ . '/settings.included.php';
      
  5. Actual result: config directory, database credentials, salt are appended to settings.php
    /opt/drupal# cat web/sites/default/settings.php
    <?php
    require_once __DIR__ . '/settings.included.php';
    $databases['default']['default'] = array (
      'database' => 'drupal',
      'username' => 'root',
      'password' => 'abcd',
      'prefix' => '',
      'host' => 'mysqld',
      'port' => '3306',
      'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',
      'driver' => 'mysql',
    );
    $settings['hash_salt'] = 'uQJJSc9OoP-LjGLmB8hyFYsqIplsIt4LD4s2KxIhbJEmHIYr6iNTcnk6wRzfSY02vyAdwo7Jxg';
    $settings['config_sync_directory'] = 'sites/default/files/config_CQSDgwm40VWDAtA0VFF4n6jxSHm3uQEwCzh2ivdvybyMWh7acmcSAn53rz8-ZuBF7eBNneouYQ/sync';
      
  6. Now repeat the test with require instead of require_once
    $ cat default/settings.php
    <?php
    require __DIR__ . '/settings.included.php';
    
    $ docker-compose exec drupal /bin/bash
    /opt/drupal# drush -y site-install minimal
      
  7. This time settings.php will be left untouched, as expected
    /opt/drupal# cat web/sites/default/settings.php
    <?php
    require __DIR__ . '/settings.included.php';
      

Maybe we could document this in sites/default/default.settings.php ? I have opened project/drupal!488.

fengtan’s picture

Version: 8.9.x-dev » 9.1.x-dev
Status: Closed (outdated) » Needs review

Spokje made their first commit to this issue’s fork.

Version: 9.1.x-dev » 9.3.x-dev

Drupal 9.1.10 (June 4, 2021) and Drupal 9.2.10 (November 24, 2021) were the last bugfix releases of those minor version series. Drupal 9 bug reports should be targeted for the 9.3.x-dev branch from now on, and new development or disruptive changes should be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.15 was released on June 1st, 2022 and is the final full bugfix release for the Drupal 9.3.x series. Drupal 9.3.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.4.x-dev branch from now on, and new development or disruptive changes should be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.9 was released on December 7, 2022 and is the final full bugfix release for the Drupal 9.4.x series. Drupal 9.4.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.5.x-dev branch from now on, and new development or disruptive changes should be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

smustgrave’s picture

Status: Needs review » Needs work

Can the MR be updated for 10.1 please.

cafuego’s picture

This issue is now making my drush calls fail on Drupal 10.1 because my skeleton settings.php used require_once to grab pretty much *all* actual config from a place I manage with config-as-code tools. When I run drush I get:

In Settings.php line 171:                                                    
    Missing $settings['hash_salt'] in settings.php.

Of course, when Drupal is accessed through the web server, it bootstraps fine and everything works as expected.

szeidler’s picture

We're running into the same issue as #19. The error is triggered when using `include_once`. With `include` it works just fine.

For us the error message only happens when using Drush 12. With Drush 11 it works fine.

In Settings.php line 171:                                                    
    Missing $settings['hash_salt'] in settings.php.

Version: 9.5.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

brad.bulger’s picture

A colleague reports discovering a problem with require/require_once in 10.3. Our settings.php file requires default.settings.php and then adds some customization. What we found:

BUT instead it HAS TO BE
"require('default.settings.php')". During a cache clear request
\Drupal\Core\Site\Settings.php gets initialized twice (once before clearing,
once after). Each time Settings::initialize() invokes "require
sites/default/settings.php". It has to return the exact same information both
times. But the require_once line meant that the second time around it was
dropping default.settings.php.

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.