Preprocess functions are the bridge between Drupal’s backend logic and Twig templates. While Twig is responsible for presentation, preprocess functions prepare and structure the data before it reaches the template layer. In Drupal 10 and 11, almost every theme hook — nodes, blocks, pages, views, forms — allows preprocessing. This enables developers to add, modify, or transform variables in a controlled and cache-aware way. Understanding preprocess functions is essential for writing clean, maintainable, and scalable frontend architecture. Instead of placing logic inside Twig, professional Drupal developers use preprocess functions to keep business logic separated from presentation.
1. Where Preprocess Functions Live
Preprocess functions are placed inside your theme’s .theme file.
Example:
/themes/custom/weeklydrupal_theme/weeklydrupal_theme.theme
2. Basic Preprocess Example
Preprocess for all nodes:
function weeklydrupal_theme_preprocess_node(&$variables) {
$variables['custom_message'] = 'Prepared inside preprocess.';
}
Now in Twig:
{{ custom_message }}
This demonstrates how preprocess injects new variables into templates.
3. Preprocess Naming Convention
Pattern:
THEMENAME_preprocess_HOOK()
Examples:
weeklydrupal_theme_preprocess_page()weeklydrupal_theme_preprocess_node()weeklydrupal_theme_preprocess_block()weeklydrupal_theme_preprocess_views_view()
The hook name must match the theme hook being rendered.
4. Accessing Entity Data Properly
Inside node preprocess:
function weeklydrupal_theme_preprocess_node(&$variables) {
$node = $variables['node'];
if ($node->bundle() === 'article') {
$variables['is_article'] = TRUE;
$variables['article_author'] = $node->getOwner()->getDisplayName();
}
}
Twig:
{% if is_article %}
<p>Written by {{ article_author }}</p>
{% endif %}
5. Adding CSS Classes Dynamically
Professional theming often requires dynamic classes.
function weeklydrupal_theme_preprocess_node(&$variables) {
$node = $variables['node'];
$variables['attributes']['class'][] = 'content-type-' . $node->bundle();
}
This adds bundle-based classes safely.
6. Working with Render Arrays in Preprocess
Example: Modify a field before rendering.
function weeklydrupal_theme_preprocess_node(&$variables) {
if (isset($variables['content']['field_ai_summary'])) {
$variables['content']['field_ai_summary']['#prefix'] = '<div class="ai-wrapper">';
$variables['content']['field_ai_summary']['#suffix'] = '</div>';
}
}
This preserves:
- Field formatter
- Access control
- Cache metadata
7. Avoiding Logic Inside Twig
Wrong approach:
{% if node.field_status.value == 1 %}
<div>Active</div>
{% endif %}
Correct approach:
function weeklydrupal_theme_preprocess_node(&$variables) {
$node = $variables['node'];
$variables['is_active'] = ($node->get('field_status')->value == 1);
}
Twig:
{% if is_active %}
<div>Active</div>
{% endif %}
8. Cache Awareness in Preprocess
When adding dynamic variables, consider caching.
If logic depends on:
- User role
- Language
- URL
You must add cache contexts.
Example:
use Drupal\Core\Cache\CacheableMetadata;
function weeklydrupal_theme_preprocess_node(&$variables) {
$cache_metadata = new CacheableMetadata();
$cache_metadata->addCacheContexts(['user.roles']);
$cache_metadata->applyTo($variables);
}
Without proper cache contexts, output may be incorrect.
9. When to Use Preprocess vs Services
Use preprocess when:
- Preparing display variables
- Adding template-specific logic
- Adjusting render arrays
Use services when:
- Business logic is complex
- Data comes from API
- Reusable logic needed across modules
Preprocess should stay lightweight and presentation-focused.
10. Real Enterprise Pattern
Common enterprise structure:
- Service fetches data
- Controller prepares response
- Preprocess formats for display
- Twig renders output
This separation ensures maintainability and testability.
Common Mistakes
- Heavy business logic inside preprocess
- Not considering cache contexts
- Accessing raw values instead of render arrays
- Forgetting to clear cache
- Naming preprocess hook incorrectly
Interview Questions (Frontend Drupal)
1. What is the purpose of a preprocess function?
Expected Answer:
To prepare and manipulate variables before they are passed to Twig templates.
2. Where are preprocess functions defined?
Expected Answer:
Inside the theme’s .theme file using the pattern THEMENAME_preprocess_HOOK().
3. Why should business logic not be placed inside Twig?
Expected Answer:
Twig is presentation-only. Logic should live in preprocess functions, services, or controllers for maintainability and separation of concerns.
4. How do you add dynamic classes in preprocess?
Expected Answer:
Modify $variables['attributes']['class'][] safely inside preprocess.
5. Why is cache context important in preprocess?
Expected Answer:
Because output may vary by user role, language, or URL, and without cache contexts Drupal may serve incorrect cached content.
6. When would you use a service instead of preprocess?
Expected Answer:
When logic is complex, reusable, or involves external APIs.