Twig中{{attributes}}与硬编码属性的适用场景?Drupal开发解惑
Great question—this is such a common sticking point when you’re ramping up on Drupal theming, especially if you’re coming from a straight HTML/CSS background where hard-coding feels second nature. Let’s break down the "why" behind Drupal’s approach, and when to use each method.
Key Advantages of create_attribute() Over Hard-Coding
1. Preserves Inherited Attributes from Drupal Core/Modules
Drupal’s ecosystem often injects critical attributes into templates behind the scenes—think cache tags, layout classes, accessibility attributes, or module-specific hooks that add styling or functionality. When you hard-code attributes like class, you’re replacing those inherited values entirely.
For example: If a contrib module adds a region--cache-optimized class to your header region to enable specific caching behaviors, hard-coding <div class='region region--header'> would wipe that class out. Using create_attribute() lets you merge your custom classes with the pre-existing ones:
{% set region_attr = create_attribute({'class': ['region', 'region--header']}) %} {# If Drupal passes additional classes via the 'attributes' variable, merge them in #} {% if attributes %} {% do region_attr.addClass(attributes.classes) %} {% endif %} <div{{ region_attr }}>{{ content }}</div>
2. Cleaner, More Maintainable Dynamic/Conditional Attributes
You mentioned conditional logic, and while you can write conditional classes in hard-coded strings, create_attribute() makes this far more readable and less error-prone—especially as your logic grows.
Compare this hard-coded approach (messy, easy to miss a space or quote):
<div class='region region--header {% if is_front %}region--front{% endif %} {% if user.isAuthenticated %}region--logged-in{% endif %}'> {{ content }} </div>
To this create_attribute() version (organized, scalable):
{% set region_attr = create_attribute({'class': ['region', 'region--header']}) %} {% if is_front %} {% do region_attr.addClass('region--front') %} {% endif %} {% if user.isAuthenticated %} {% do region_attr.addClass('region--logged-in') %} {% endif %} <div{{ region_attr }}>{{ content }}</div>
It also handles non-class attributes (like data-*, aria-*, or id) just as cleanly, without juggling multiple string concatenations.
3. Follows Drupal Theming Best Practices
Drupal’s template system is built around the attributes object pattern. Using create_attribute() aligns your code with how core and contrib modules expect themes to work, making your templates easier for other Drupal developers to read and maintain. It also ensures automatic escaping of attribute values, which prevents XSS vulnerabilities that can creep in when hard-coding dynamic values.
When to Use create_attribute()
- When you need to merge custom attributes with Drupal-provided ones: If your template receives an
attributesvariable (common in node, block, region, or field templates), usecreate_attribute()to extend it instead of replacing it. - When working with dynamic/conditional attributes: Any time you’re adding classes, data attributes, or other properties based on page context, user roles, content types, etc.—
create_attribute()keeps your logic organized. - When managing multiple attribute types: If your element needs a mix of
class,id,aria-label,data-*attributes,create_attribute()lets you define and modify them in one place instead of scattering them across an HTML tag.
When to Use {{ attributes }} Instead of Hard-Coding
The {{ attributes }} variable is a pre-built Attribute object that Drupal passes to templates with all the core/module-generated attributes. You should almost never replace it with hard-coded attributes—doing so breaks core functionality, accessibility, and module integrations.
For example, in a node template, {{ attributes }} includes classes like node, node--type-article, node--published, plus accessibility roles and cache-related attributes. Instead of hard-coding, extend it:
{% set node_attr = attributes.addClass('my-custom-node-styling') %} <article{{ node_attr }}> {{ content }} </article>
Only hard-code attributes if you’re creating a completely standalone HTML element that has no connection to Drupal’s entities, blocks, or regions—like a purely decorative div with no dynamic logic or backend integration.
内容的提问来源于stack exchange,提问作者Rob Monhemius

