Configuration scheme
Drupal 8 includes support for a configuration schema/metadata language based on Kwalify (http://www.kuwata-lab.com/kwalify/) for YAML configuration files. Kwalify itself is written in Ruby and required some modifications for our purposes, so not all Kwalify details apply directly, but it's quite close.
Cheatsheet
For a quick understanding and some helpful examples, refer to this cheat sheet, and continue reading if you still have questions:
/sites/default/files/config-schema-cheat-sheet1.5.pdf
Introductory Example
The System module has two configuration parameters related to maintenance mode (whether the site is in offline mode for visitors):
<?php $config = \Drupal::config('system.maintenance'); $message = $config->get('message'); $langcode = $config->get('langcode'); ?>
(Note: Whether maintenance is enabled is stored in the state system, not configuration.)
The default values for this configuration object are stored in core/modules/system/config/install/system.maintenance.yml
as:
message: '@site is currently under maintenance. We should be back shortly. Thank you for your patience.' langcode: en
Each module can have as many configuration objects as needed. These are defined in one or more schema files provided with the module. In the System module, these files are found in core/modules/system/config/schema
. The relevant section from system.schema.yml
looks like:
system.maintenance: type: config_object label: 'Maintenance mode' mapping: message: type: text label: 'Message to display when in maintenance mode'
The top-level key (system.maintenance
) in the schema file corresponds to the base filename system.maintenance.yml
and to the configuration object name config('system.maintenance')
. The nested levels describe what is inside the file. Configuration schema predefines two file types: config_object
for global configuration files and config_entity
for entities. config_object
is defined in core.data_types.schema.yml as:
# Root of a configuration object. _core_config_info: type: mapping mapping: default_config_hash: type: string label: 'Default configuration hash' config_object: type: mapping mapping: langcode: type: string label: 'Language code' _core: type: _core_config_info
The mapping
type is a basic type for key-value pairs. Using config_object
, the maintenance mode schema reuses keys langcode
and _core
and adds a message
key. The label: 'Maintenance mode'
describes the schema’s contents. The mapping section defines message
while inheriting langcode
and _core
from the base type. Each item has a type
and label
key describing the data and its UI label.
In all core-supported cases, the top-level item in the .yml
config file is a mapping described by the schema’s mapping list. You should use either config_object
or config_entity
subtypes. Items in the mapping can be of any type depending on the data. The _core
key and all keys within it are reserved for Drupal core.
What Are Schema Files Used For?
1. To support multilingual features. We need tools to identify all translatable strings in shipped configuration so that we can offer translation suggestions via https://localize.drupal.org.
2. Schemas are used to create translation forms for config settings. The schema guides what fields are shown and how they behave in the translation UI.
3. Configuration schema is used by the persistence layer to correctly export configuration. You can skip writing schema if you implement toArray()
in your config entity.
4. Schemas enforce value typecasting (e.g., strings vs integers) so deployment diffs reflect real changes and not accidental type changes.
5. PHPUnit's TestBase enforces default schema compliance. You can disable this with:
protected $strictConfigSchema = FALSE;
See https://drupal.org/project/config_inspector for a module that helps debug and inspect your schema.
There are more advanced use cases, such as generating web service interfaces based on schema metadata.
Properties
- type: The value's type; can be a base or derived type (see examples below).
- label: A UI label for the value. It does not have to match the form label exactly, but consistency improves clarity.
- translatable: Indicates whether the value should be translatable. You can use:
type: label
as a shorthand for:
type: string translatable: true
- nullable: Whether the value can be null. Defaults to false if not specified.
- class: Used for base types to assign a parsing class (examples below for TypedData and config types).
- Type-specific properties:
mapping: Used for mapping
types, listing the keys and value types.
sequence: Used for sequence
types, listing the type of elements in a list.
Types Supported in Schema Files
As mentioned, basic types and some complex types are defined in core.data_types.schema.yml:
undefined: label: 'Undefined' class: '\Drupal\Core\Config\Schema\Undefined' ignore: label: 'Ignore' class: '\Drupal\Core\Config\Schema\Ignore' boolean: label: 'Boolean' class: '\Drupal\Core\TypedData\Plugin\DataType\BooleanData' email: label: 'Email' class: '\Drupal\Core\TypedData\Plugin\DataType\Email' integer: label: 'Integer' class: '\Drupal\Core\TypedData\Plugin\DataType\IntegerData' float: label: 'Float' class: '\Drupal\Core\TypedData\Plugin\DataType\FloatData' string: label: 'String' class: '\Drupal\Core\TypedData\Plugin\DataType\StringData' uri: label: 'Uri' class: '\Drupal\Core\TypedData\Plugin\DataType\Uri'
Complex types:
mapping: label: Mapping class: '\Drupal\Core\Config\Schema\Mapping' definition_class: '\Drupal\Core\TypedData\MapDataDefinition' sequence: label: Sequence class: '\Drupal\Core\Config\Schema\Sequence' definition_class: '\Drupal\Core\TypedData\ListDataDefinition'
Mappings are associative arrays with explicitly defined keys. Sequences are indexed arrays where all items are of the same type.
Example Custom Complex Type
Defining a reusable "mail" type for email configuration:
mail: type: mapping label: 'Mail' mapping: subject: type: label label: 'Subject' body: type: text label: 'Body'
This "mail" type can be reused in schemas, such as:
user.mail: type: config_object label: 'Email settings' mapping: cancel_confirm: type: mail label: 'Account cancellation confirmation' password_reset: type: mail label: 'Password recovery'
Dynamic Type References
Types can be dynamic using placeholders:
[%key]
: Uses the current key name[%parent]
: Uses a parent key- Combos like
views.field.[table]-[field]
Example: image effects depend on the id
field, so schema must dynamically reference that.
Naming Your Schema Files
Use globally unique names, preferably prefixed with your module name, to avoid conflicts.
Schema File Coding Style
- Use single quotes for all strings
- Do not quote keys or type names
- Use consistent indentation (YAML requires it)
- Provide meaningful labels for translatable strings
PHP API
To access typed configuration metadata:
$definition = \Drupal::service('config.typed')->getDefinition('system.maintenance');
Debugging Your Schema
Use the Config Inspector module to debug schema issues, check for missing types, and preview generated forms.
More Reference
Drupal’s online documentation is © 2000-2020 by the individual contributors and can be used in accordance with the Creative Commons License, Attribution-ShareAlike 2.0. PHP code is distributed under the GNU General Public License.