Configuration Management feature
Edit on GitHubWhat It Does
Provides a centralized, schema-driven system for managing application settings across scopes (for example global, store, custom-scope). Settings are declared in YAML files, managed via the Back Office UI, to be consumed in different layers (Zed, Yves, Glue) through module Config classes.
Quick Start
1. Declare settings in a YAML schema
# /data/configuration/my-module.configuration.yml
features:
- key: my_module
name: My Module
tabs:
- key: general
name: General
groups:
- key: display
name: Display Settings
scopes: [global, store]
settings:
- key: items_per_page
name: Items Per Page
type: integer
default_value: 24
scopes: [global, store]
storefront: true
constraints:
- type: required
message: Items per page is required
- type: min
message: Must be at least 1
options: { min: 1 }
2. Sync schemas
docker/sdk cli console configuration:sync
3. Consume in your module Config
namespace Spryker\Yves\MyModule;
use Spryker\Yves\Kernel\AbstractBundleConfig;
class MyModuleConfig extends AbstractBundleConfig
{
protected const int DEFAULT_ITEMS_PER_PAGE = 24;
protected const string CONFIGURATION_KEY_MY_MODULE_GENERAL_DISPLAY_ITEMS_PER_PAGE = 'my_module:general:display:items_per_page';
public function getItemsPerPage(): int
{
return $this->getModuleConfig(static::CONFIGURATION_KEY_MY_MODULE_GENERAL_DISPLAY_ITEMS_PER_PAGE, static::DEFAULT_ITEMS_PER_PAGE);
}
}
The getModuleConfig() method is available in Zed, Yves, Glue layers AbstractBundleConfig and is the preferred way to read configuration values.
Reading Configuration Values
The getModuleConfig() Method
Every AbstractBundleConfig in Zed, Yves, and Glue provides:
protected function getModuleConfig(
string $key,
mixed $default = null,
array $configurationScopes = [],
): mixed
| Parameter | Type | Description |
|---|---|---|
$key |
string | Compound setting key: feature:tab:group:setting |
$default |
mixed | Fallback when value is not found or Configuration module is not installed |
$configurationScopes |
ConfigurationScopeTransfer[] |
Optional scope context transfers |
Layer behavior:
- Yves / Glue: Reads from key-value storage via
ConfigurationClient(fast, cached) - Zed: Reads from database via
ConfigurationFacade(supports secrets, full scope resolution)
Backward Compatible: If the Configuration module is not installed, getModuleConfig() silently returns $default.
Real-World Examples
AvailabilityWidget (Yves) – boolean setting with constant fallback:
class AvailabilityWidgetConfig extends AbstractBundleConfig
{
protected const bool STOCK_DISPLAY_ENABLED = false;
public const string STOCK_DISPLAY_MODE_INDICATOR_AND_QUANTITY = 'indicator_and_quantity';
protected const string CONFIGURATION_KEY_CATALOG_INVENTORY_STOCK_OPTIONS_DISPLAY_STOCK_AVAILABILITY = 'catalog:inventory:stock_options:display_stock_availability';
protected const string CONFIGURATION_KEY_CATALOG_INVENTORY_STOCK_OPTIONS_STOCK_INFO_OPTIONS = 'catalog:inventory:stock_options:stock_info_options';
public function isStockDisplayEnabled(): bool
{
return $this->getModuleConfig(static::CONFIGURATION_KEY_CATALOG_INVENTORY_STOCK_OPTIONS_DISPLAY_STOCK_AVAILABILITY, static::STOCK_DISPLAY_ENABLED);
}
public function getStockDisplayMode(): string
{
return $this->getModuleConfig(static::CONFIGURATION_KEY_CATALOG_INVENTORY_STOCK_OPTIONS_STOCK_INFO_OPTIONS, static::STOCK_DISPLAY_MODE_INDICATOR_AND_QUANTITY);
}
}
BuyBox (Yves) – string setting with enum fallback:
class BuyBoxConfig extends AbstractBundleConfig
{
public const string SORT_BY_PRICE = 'price';
protected const string CONFIGURATION_KEY_MARKETPLACE_PDP_BUY_BOX_OFFER_SORT_RULE = 'marketplace:pdp:buy_box:offer_sort_rule';
public function getSortingStrategy(): string
{
return $this->getModuleConfig(static::CONFIGURATION_KEY_MARKETPLACE_PDP_BUY_BOX_OFFER_SORT_RULE, static::SORT_BY_PRICE);
}
}
Scope-Specific Reads
Pass ConfigurationScopeTransfer objects as the third argument when you need a scope-specific value:
use Generated\Shared\Transfer\ConfigurationScopeTransfer;
public function getItemsPerPage(string $storeName): int
{
protected const string CONFIGURATION_KEY_MY_MODULE_GENERAL_DISPLAY_ITEMS_PER_PAGE = 'my_module:general:display:items_per_page';
return $this->getModuleConfig(
static::CONFIGURATION_KEY_MY_MODULE_GENERAL_DISPLAY_ITEMS_PER_PAGE,
static::DEFAULT_ITEMS_PER_PAGE,
[
(new ConfigurationScopeTransfer())
->setKey('store')
->setIdentifier($storeName),
],
);
}
Integration Checklist
When integrating Configuration into an existing module:
- Identify hardcoded values or constants that should be configurable
- Declare them in a YAML schema in
data/configuration/ - Replace hardcoded access in the module’s Config class with
getModuleConfig()calls - Keep the original constant as
$defaultfor backward compatibility - Run
configuration:sync - Values are now manageable via the Back Office Configuration Management page
YAML Schema Declaration Reference
Schema Validation
YAML schema files support IDE autocompletion via JSON Schema. Add this header to your file:
# yaml-language-server: $schema=../../vendor/spryker/configuration/resources/configuration/configuration-schema-v1.json
The schema file is located at vendor/spryker/configuration/resources/configuration/configuration-schema-v1.json.
Hierarchy
features[]
tabs[]
groups[]
settings[]
Each setting gets a compound key: {featureKey}:{tabKey}:{groupKey}:{settingKey} used for persistence and lookups.
Feature Level
features:
- key: system # Required. Unique feature identifier.
name: System Configuration # Required. Display name in backoffice.
description: Core system settings # Optional. Feature description.
order: 0 # Optional. Sort order (lower = first).
enabled: true # Optional. Default: true.
tabs: [...] # Required. At least one tab.
| Property | Type | Required | Default | Constraints | Description |
|---|---|---|---|---|---|
key |
string | Yes | – | ^[a-z][a-z0-9_]*$ |
Unique identifier. Part of compound setting key. |
name |
string | Yes | – | 1-255 chars | Display name in backoffice sidebar. |
description |
string | No | null |
max 1000 chars | Feature description text. |
order |
integer | No | 0 |
– | Sort order for rendering. Lower values first. |
enabled |
boolean | No | true |
– | When false, feature and all children are hidden. |
tabs |
array | Yes | – | min 1 item | List of tab objects. |
Tab Level
tabs:
- key: general # Required. Unique within feature.
name: General # Required. Tab display name.
icon: settings # Optional. Icon class for backoffice tab.
description: General system settings # Optional. Tab description.
order: 0 # Optional. Sort order (lower = first).
enabled: true # Optional. Default: true.
groups: [...] # Required. At least one group.
| Property | Type | Required | Default | Constraints | Description |
|---|---|---|---|---|---|
key |
string | Yes | – | ^[a-z][a-z0-9_]*$ |
Unique within feature. Part of compound setting key. |
name |
string | Yes | – | 1-255 chars | Tab label in backoffice. |
icon |
string | No | null |
max 100 chars | Icon class (for example settings, cable, trending_up). |
description |
string | No | null |
max 1000 chars | Tab description text. |
order |
integer | No | 0 |
– | Sort order for rendering. Lower values first. |
enabled |
boolean | No | true |
– | When false, tab and all children are hidden. |
groups |
array | Yes | – | min 1 item | List of group objects. |
Group Level
groups:
- key: basic # Required. Unique within tab.
name: Basic Settings # Required. Group display name.
description: Basic system config # Optional. Group description.
scopes: [global, store] # Required. Scopes this group is visible for.
order: 0 # Optional. Sort order (lower = first).
enabled: true # Optional. Default: true.
settings: [...] # Required. At least one setting.
| Property | Type | Required | Default | Constraints | Description |
|---|---|---|---|---|---|
key |
string | Yes | – | ^[a-z][a-z0-9_]*$ |
Unique within tab. |
name |
string | Yes | – | 1-255 chars | Group heading in backoffice. |
description |
string | No | null |
max 1000 chars | Group description text. |
scopes |
string[] | Yes | ['global'] |
min 1 item | Scopes where this group is displayed in backoffice. |
order |
integer | No | 0 |
– | Sort order for rendering. Lower values first. |
enabled |
boolean | No | true |
– | When false, group and all settings are hidden. |
settings |
array | Yes | – | min 1 item | List of setting objects. |
Setting Level
settings:
- key: site_name # Required. Unique within group.
name: Site Name # Required. Setting label.
description: The name of the site # Optional. Displayed below the input.
note: Changes require cache clear # Optional. Additional note below description.
placeholder: Enter your store name # Optional. Input placeholder text.
help_text: Appears in page titles # Optional. Tooltip or help area text.
template: '@MyModule/Configuration/custom-input.twig' # Optional. Custom Twig template.
type: string # Required. Data type.
default_value: My Store # Optional. Fallback value.
options: # Optional. For select/multiselect/radio types.
- value: option_a
label: Option A
scopes: [global, store] # Optional. Default: ['global'].
order: 0 # Optional. Sort order (lower = first).
enabled: true # Optional. Default: true.
secret: false # Optional. Default: false.
storefront: true # Optional. Default: false.
constraints: [...] # Optional. Validation constraints.
dependencies: [...] # Optional. Conditional visibility rules.
| Property | Type | Required | Default | Constraints | Description |
|---|---|---|---|---|---|
key |
string | Yes | – | ^[a-z][a-z0-9_]*$ |
Unique within group. Part of compound key. |
name |
string | Yes | – | 1-255 chars | Input label in backoffice. |
description |
string | No | null |
max 1000 chars | Help text displayed below the input field. |
note |
string | No | null |
max 1000 chars | Additional note displayed below the description in italic. |
placeholder |
string | No | null |
max 255 chars | Placeholder text inside the input field. |
help_text |
string | No | null |
max 500 chars | Extended help in tooltip or expandable area. |
template |
string | No | null |
max 255 chars | Custom Twig template. Overrides type-based widget. |
type |
string | Yes | – | See types table | Value data type. Determines backoffice input widget. |
default_value |
mixed | No | null |
Must match type |
Fallback when no value is saved at any scope. |
options |
option[] | No | [] |
For select/multi/radio | Available choices. See Options. |
scopes |
string[] | No | ['global'] |
min 1 item | Scopes where this setting can be configured. |
order |
integer | No | 0 |
– | Sort order for rendering. Lower values first. |
enabled |
boolean | No | true |
– | When false, setting is excluded from schema. |
secret |
boolean | No | false |
– | When true, value is encrypted in database. Never published to storage. |
storefront |
boolean | No | false |
– | When true, value is published to key-value storage for Yves/Glue. |
constraints |
array | No | [] |
– | Validation rules. See Constraints. |
dependencies |
array | No | [] |
– | Conditional rules. See Dependencies. |
Setting Types
| Type | Description | Backoffice Input | Requires options |
|---|---|---|---|
string |
Single-line text | Text input | No |
integer |
Whole number | Number input | No |
float |
Decimal number | Number input | No |
boolean |
True/false toggle | Checkbox/switch | No |
text |
Multi-line text or structured data | Textarea | No |
color |
Color hex value | Color picker | No |
json |
JSON structure | Code editor | No |
select |
Single choice from list | Dropdown | Yes |
multiselect |
Multiple choices from list | Multi-select | Yes |
radio |
Single choice from list | Radio buttons | Yes |
Options
Required for select, multiselect, and radio types. Defines available choices.
options:
- value: indicator_only
label: Indicator Only
description: Show only in-stock/out-of-stock indicator
- value: indicator_and_quantity
label: Indicator and Quantity
description: Show indicator and exact stock count
| Property | Type | Required | Constraints | Description |
|---|---|---|---|---|
value |
string | Yes | min 1 char | Internal value stored when selected. |
label |
string | Yes | 1-255 chars | Display label shown in backoffice. |
description |
string | No | max 500 chars | Additional explanation (for radio buttons). |
Secret vs Storefront Behavior
secret |
storefront |
Behavior |
|---|---|---|
false |
false |
Plain text in database. Accessible only via Zed (getModuleConfig() in Zed Config). |
false |
true |
Plain text. Published to key-value storage. Accessible in all layers via getModuleConfig(). |
true |
false |
Encrypted in database. Decrypted on read in Zed only. Never published to storage. |
true |
true |
Invalid combination. Secrets are always excluded from storage. |
Available Scopes
Built-in scopes (enabled out of the box):
| Scope | Description | Requires Identifier |
|---|---|---|
global |
Application-wide default | No |
store |
Store-specific override (for example DE, AT) | Yes |
Default hierarchy: store -> global -> default_value. Values resolve from most specific to least specific.
For adding custom scopes, see Adding Custom Scopes.
Constraints
Validated server-side when saving values through the backoffice.
constraints:
- type: required
message: Site name is required
- type: min
message: Must be at least 1
options:
min: 1
- type: max
message: Cannot exceed 100
options:
max: 100
| Property | Type | Required | Constraints | Description |
|---|---|---|---|---|
type |
string | Yes | See table | Constraint type identifier. |
message |
string | Yes | 1-500 chars | Error message shown when validation fails. |
options |
object | No | Depends on type | Constraint-specific parameters. |
Built-in Constraint Types
| Type | Description | Required Options | Example |
|---|---|---|---|
required |
Value must not be blank | – | Mandatory fields |
min |
Minimum numeric value | min (number) |
options: { min: 1 } |
max |
Maximum numeric value | max (number) |
options: { max: 100 } |
range |
Value within numeric range | min, max (number) |
options: { min: 0, max: 100 } |
length |
String length limits | min and/or max |
options: { min: 6, max: 128 } |
email |
Email format validation | – | Email input fields |
url |
URL format validation | – | URL input fields |
regex |
Pattern matching | pattern (string) |
options: { pattern: '^G-[A-Z0-9]{10}$' } |
choice |
Value from allowed list | choices (string[]) |
options: { choices: ['a', 'b'] } |
Dependencies
Control conditional visibility of settings in the backoffice UI. A setting with dependencies is only shown when at least one dependency rule matches (OR logic between rules). Each rule uses a when clause with any (OR) or all (AND) condition grouping.
settings:
- key: stock_info_options
name: Stock Info Options
type: radio
dependencies:
- when:
any:
- setting: catalog:inventory:stock_options:display_stock_availability
operator: equals
value: "true"
Multiple conditions with all (AND logic):
dependencies:
- when:
all:
- setting: system:general:basic:feature_enabled
operator: equals
value: "true"
- setting: system:general:basic:mode
operator: not_equals
value: maintenance
Dependency Rule
| Property | Type | Required | Description |
|---|---|---|---|
when |
object | Yes | Contains any or all array of conditions. |
When Clause
| Property | Type | Required | Description |
|---|---|---|---|
any |
condition[] | No | Setting is shown if any condition matches (OR). |
all |
condition[] | No | Setting is shown if all conditions match (AND). |
One of any or all must be provided.
Condition
| Property | Type | Required | Description |
|---|---|---|---|
setting |
string | Yes | Compound key of the setting this depends on. |
operator |
string | Yes | Comparison operator. |
value |
string | Yes | Value to compare against. |
Dependency Operators
| Operator | Description |
|---|---|
equals |
Setting value must equal the given value. |
not_equals |
Setting value must not equal the given value. |
greater_than |
Numeric: value must be greater than expected. |
less_than |
Numeric: value must be less than expected. |
contains |
String: value must contain the expected text. |
in |
Value must be in the given list. |
Schema File Locations
| Location | Purpose | Loaded By |
|---|---|---|
{Module Folder}/resources/configuration/ |
Core module schemas | configuration:sync |
data/configuration/ |
Project-level schema overrides | configuration:sync |
Project schemas override core schemas at the setting level. Settings with the same compound key are completely replaced.
Merged output: data/configuration/merged-schema.php
Backoffice Management
Settings are managed at The Back office > Configuration. The page provides:
- Feature sidebar navigation
- Tabbed layout per feature
- Scope switcher (global, store with identifier)
- Input widgets matching setting types
- Inline validation with constraint error messages
- “Revert to default” to delete scope-specific overrides
- Batch save with per-field error reporting
Common Issues
| Symptom | Cause | Solution |
|---|---|---|
getModuleConfig() always returns default |
Setting storefront: false |
Yves/Glue can only read storefront-enabled settings. Set storefront: true or use Zed Config. |
getModuleConfig() always returns default |
Configuration module not installed | Expected behavior. Method gracefully falls back to $default. |
Value returns null despite being saved |
Key mismatch | Compound key format is feature:tab:group:setting. Verify all four segments match the YAML schema. |
| Secret value empty in Yves | Expected behavior | Secrets are never published to storage. Access only via Zed. |
| Changes not visible after YAML edit | Schema not synced | Run configuration:sync after YAML changes. |
| Store-specific value not applied | Missing scope context | Pass ConfigurationScopeTransfer in third argument or register request expander plugins. See Adding Custom Scopes. |
Thank you!
For submitting the form