Config Actions - Advanced Patterns
When to Use
Use advanced config action patterns when you need wildcards for bulk operations, optional config handling, chaining multiple actions, or input substitution.
Complex config action scenarios: wildcards, optional config, chaining, input substitution.
Steps: Wildcards, Optional Config, Substitution and Chaining
-
Wildcards for bulk operations — Target multiple entities with patterns
config: actions: user.role.*: grantPermission: 'access content' core.entity_view_display.node.*.default: setComponent: name: created options: { type: timestamp, weight: 10 } -
Optional config actions — Prefix with
?to skip if config doesn't existconfig: actions: ?block.block.legacy_block: setProperties: status: false -
Input substitution — Use
${input_name}in config names or valuesinput: theme_name: data_type: string default: { source: value, value: olivero } config: actions: block.block.${theme_name}_search: placeBlockInRegion: region: header theme: ${theme_name} -
Chaining actions — Multiple actions on same config entity
config: actions: user.role.editor: createIfNotExists: label: 'Editor' grantPermissions: - 'access content' - 'access toolbar' setProperties: weight: 5 -
Drupal token substitution — Use Drupal tokens in config values (separate from
${input}syntax)Token syntaxconfig: actions: metatag.metatag_defaults.node: simpleConfigUpdate: tags.og_title: '[node:title]' tags.og_url: '[site:url]/node/[node:nid]'[entity:field]is processed by Drupal's token system at runtime, not at recipe apply time. Only useful for config values that support tokens (metatag, pathauto, etc.). -
Create entities then configure — Use createIfNotExists before entity-specific actions
config: actions: core.entity_form_display.node.article.default: createIfNotExists: targetEntityType: node bundle: article mode: default setComponents: - name: body options: { type: text_textarea_with_summary }
Decision Points: Choosing an Advanced Pattern
| At this step... | If... | Then... |
|---|---|---|
| Config may not exist | Action should be optional | Prefix config name with ? |
| Multiple entities need same action | Entities share config prefix pattern | Use wildcards like user.role.* |
| Action values vary by input | Recipe needs environment flexibility | Use ${input_name} substitution |
| Actions must run in sequence | Later action depends on earlier | YAML order matters; earlier actions run first |
Common Mistakes
- Using wildcards with optional prefix →
?user.role.*is invalid; wildcards and optional are mutually exclusive - Forgetting input values are strings →
${site_name}is always string; no type coercion for integers/booleans - Not testing wildcard patterns → Wildcards only match existing config; create first, then wildcard-modify
- Assuming action order doesn't matter → YAML dict order is preserved; actions run in declaration order
- Missing createIfNotExists before entity-specific actions → Entity must exist or be created in same recipe
See Also
- Previous: ← Config Actions - Entity-Specific
- Next: Input System - Defining Inputs →
- Reference:
core/lib/Drupal/Core/Config/Action/ConfigActionManager.php(applyAction method)