Step 4: Convert Drupal 7 Variables to Drupal 8 Configuration
In Drupal 7 and before one of the common ways of storing settings was using variable_get()
and variable_set()
. In Drupal 8 these have been replaced with the new configuration system API/storage.
System values that could be reset, and unlike configuration would not be edited by end users or transferred between Drupal instances, can be implemented via State API instead of Config API. See How to upgrade D7 variables to D8's state system.
Short introduction to CMI
- Modules store default settings in configuration files that are stored in a
config/install/
directory in the module root directory. - When a module is enabled these default settings are copied to the active configuration in the site's database.
- When settings are changed by a site administrator these are stored in the active configuration in the database, which can be exported back to files.
Upgrade procedure
- Decide on a config object name and a name for the settings. Simple settings can be stored in a config object named
<module_name>.settings.yml
, while for more complex settings it is advisable to use sub-keys. See the guidelines below. - Create a directory named
config
in your module's root directory. - In
config/install
, create the default settings file with the default configuration. The filename convention is<module_name>.<config_object_name>.<optional_sub_key>.yml
. For example, this is the config file for the 'large' image style from the Image module (image.style.large.yml
):
name: large label: 'Large (480x480)' effects: ddd73aa7-4bd6-4c85-b600-bdf2b1628d1d: id: image_scale data: width: 480 height: 480 upscale: true weight: '0' ieid: ddd73aa7-4bd6-4c85-b600-bdf2b1628d1d
- Grep the entire code base and replace all instances of
variable_get()
andvariable_set()
with\Drupal::config()->get()
and\Drupal::configFactory()->getEditable()->set()
. An example:
$items_per_page = \Drupal::config('node.settings')->get('items_per_page');
function node_form_system_site_information_settings_form_submit($form, &$form_state) { \Drupal::configFactory()->getEditable('node.settings') ->set('items_per_page', $form_state['values']['default_nodes_main']) ->save(); }
In a namespace, for example a form class, use \Drupal::config() instead of Drupal::config().
- Create a migration to allow sites using previous versions of Drupal and your module to upgrade. A well documented example can be found at Migrate API documentation page. Configuration entities are more complex and you will probably have to write a migration source plugin but a destination plugin for entities already exists.
- Update overrides in
settings.php
. See Configuration override system.
Guidelines
- Within your conversion issue work, convert one variable at a time.
- Determine the variable name to convert.
- Grep the entire Drupal code base for the variable name and identify all instances that need to be updated.
- Speed up greps by checking
/core
first. But do not forget to grep/profiles
.
- New configuration objects are only picked up when a module is first enabled. If you add a new configuration to a module that is already enabled, you should disable, uninstall and re-enable the module for the configuration files to appear.
- Keep configuration object names short and concise.
-
If a module has only one set of settings (i.e., one setting form that will result in one configuration object), then the standard configuration object name is
$module.settings
.The following bullets only apply to modules that need multiple configuration objects, in which case "settings" would be ambiguous:
- Given a module settings form
system_site_information_settings_form()
that manages the variables:
site_name site_mail site_frontpage site_403 ...
- Understand that the primary namespace/owner of the configuration object is System module, so the configuration object name has to start with
system.
- Do not convert the form constructor function's name as-is for the configuration object name (
system.site-information
). No Drupal developer wants to have to remember or deal with needlessly long names on a daily basis. - Instead, find the common denominator and shortest basename of all variables (
site
) and choose an appropriate configuration object name:
system.site
-
- Strip the configuration object name (or parts of it) from key names.
- Given a new configuration object name:
system.site
and a variable name:
site_name
- Understand that converting
site_name
intosystem.site:site_name
is bad DX. - Instead, remove the duplicate
site_
from the key name; i.e.:
system.site:name
- Given a new configuration object name:
- Leverage sub-keys.
- Determine and understand the meaning of the entire set of variables to be converted.
- Given a subset of variables:
site_frontpage site_403 site_404
- Research a bit to understand that all of them refer to internal router paths that denote pages to be shown in certain cases.
- Do not convert them to meaningless
frontpage
,403
,404
. - Instead, leverage sub-keys and introduce DX sanity for D8 developers:
page.front page.403 page.404
- Direct access, or provide context.
\Drupal::config('system.site')->get('name')
is fine when being invoked only once within a function.- It's also fine, if the respective code is only reached through certain code conditions.
- However, when
Drupal::config('system.site')
is unconditionally used multiple times within a function, then only invoke it once. - Unless the context is crystal clear, try to avoid the ambiguous variable name
$config
. - Instead, use a self-descriptive variable name; e.g.:
$site_config = \Drupal::config('system.site');
- Where the configuration object name will include a dynamic item (e.g. when defining an additional per-content type configuration) you will need to use configuration entities.
- All defaults should be provided in your default settings file. Do not attempt to pass them as a second parameter or using the :? syntax.
More information
Help improve this page
You can:
- Log in, click Edit, and edit this page
- Log in, click Discuss, update the Page status value, and suggest an improvement
- Log in and create a Documentation issue with your suggestion