Twig Tweak

A Twig extension module that provides useful functions and filters for Drupal development, enabling easy rendering of entities, blocks, views, menus, and more directly within Twig templates.

twig_tweak
175,501 sites
258
drupal.org

Install

Drupal 11, 10 v3.4.1
composer require 'drupal/twig_tweak:^3.4'
Drupal 9 v3.3.0
composer require 'drupal/twig_tweak:^3.3'

Overview

Twig Tweak is a powerful module that extends the Twig templating engine with a comprehensive set of functions and filters specifically designed for Drupal development. It bridges the gap between Drupal's PHP-based architecture and Twig's template syntax, allowing theme developers to access Drupal functionality directly in templates without writing PHP code in preprocess hooks.

The module provides over 20 Twig functions for rendering blocks, entities, fields, views, menus, images, forms, and more. It also includes 17+ filters for common operations like token replacement, image styling, URL generation, and cache metadata handling. All functions properly handle Drupal's render array system and cache metadata, ensuring optimal performance and correct caching behavior.

For development purposes, Twig Tweak includes debugging functions like drupal_dump() and dd() for variable inspection, drupal_breakpoint() for Xdebug integration, and Drush commands for linting and debugging Twig templates. The module is designed with performance in mind, using lazy-loaded services to minimize overhead when functions aren't used.

Features

  • Render block plugins directly in Twig templates with drupal_block(), supporting custom configuration and context mapping
  • Embed Views displays with drupal_view() and check view results with drupal_view_result() for conditional rendering
  • Render any entity type with drupal_entity() supporting view modes, language codes, and access checking
  • Display entity edit/create forms with drupal_entity_form() including support for custom form modes
  • Render individual entity fields with drupal_field() using view modes or custom display options
  • Build and render menus with drupal_menu() supporting configurable depth, levels, and expansion
  • Render images by file ID, UUID, or URI with drupal_image() supporting image styles and responsive images
  • Access Drupal configuration values with drupal_config() and replace tokens with drupal_token()
  • Generate URLs and links with drupal_url() and drupal_link() including access checking
  • Render theme regions with drupal_region() for custom page layouts
  • Display status messages with drupal_messages() and breadcrumbs with drupal_breadcrumb()
  • Add contextual links to any element with drupal_contextual_links()
  • Debug variables with drupal_dump()/dd() using Symfony VarDumper integration
  • Set Xdebug breakpoints in templates with drupal_breakpoint()
  • Apply image styles to URIs with the image_style filter
  • Extract file URIs and URLs from entities and fields with file_uri and file_url filters
  • Generate entity URLs and links with entity_url and entity_link filters
  • Get entity translations with the translation filter for multilingual sites
  • Extract and bubble cache metadata with cache_metadata filter for proper caching
  • Filter render array children with the children filter
  • Perform regex replacements with preg_replace filter
  • Replace tokens in strings with token_replace filter
  • Transliterate Unicode to ASCII with transliterate filter
  • Truncate strings safely with the truncate filter
  • Create data URIs for inline embedding with data_uri filter
  • Drush commands for linting (twig-tweak:lint) and debugging (twig-tweak:debug) Twig templates
  • Extensible architecture with hooks for adding custom functions, filters, and tests

Use Cases

Render a block plugin in a custom page template

Use drupal_block() to embed block plugins directly in templates without configuring them in the block layout. Example: {{ drupal_block('system_branding_block', {use_site_name: true}) }} renders the site branding. For blocks requiring context, use context_mapping: {{ drupal_block('plugin_id', {context_mapping: {node: '@node.node_route_context:node'}}) }}

Embed Views in templates with contextual filters

Use drupal_view() to embed Views displays in templates, optionally passing contextual filter arguments. Example: {{ drupal_view('articles', 'block_1', node.id) }} embeds a view with the current node's ID as a contextual filter. Check if view has results first: {% if drupal_view_result('related', 'block_1')|length > 0 %}{{ drupal_view('related', 'block_1') }}{% endif %}

Display related content by rendering entity fields

Render specific fields from referenced entities: {{ drupal_field('field_image', 'node', node.id, 'teaser') }}. For custom display settings: {{ drupal_field('field_image', 'node', 1, {type: 'image_url', settings: {image_style: 'large'}}) }}

Create responsive images with image styles

Render images with styles using drupal_image(): {{ drupal_image('public://hero.jpg', 'wide', {alt: 'Hero image'|t}, responsive=true) }}. For images from fields, combine with filters: {% set uri = node.field_image|file_uri %}{% if uri %}{{ drupal_image(uri, 'thumbnail') }}{% endif %}

Build custom menus with specific depth

Render menus with control over levels and expansion: {{ drupal_menu('main', 2, 3) }} renders main menu starting at level 2 with depth 3. Use expand=true for fully expanded menus: {{ drupal_menu('main', expand=true) }}

Handle multilingual content in templates

Get translated entities using the translation filter: {{ media|translation.field_description|view }}. The filter uses the current language context by default or accepts a language code: {{ node|translation('fr') }}

Ensure proper caching with cache_metadata filter

When accessing raw entity values, bubble cache metadata to prevent stale content: <img src="{{ node.field_image|file_url }}" />{{ content.field_image|cache_metadata }}. This ensures the render cache is invalidated when the image changes.

Debug variables in templates during development

Use dd() (alias of drupal_dump) to inspect variables: {{ dd(node) }} dumps the node object. Call without arguments to dump all template variables: {{ dd() }}. Requires symfony/var-dumper package for best output. Use drupal_breakpoint() to trigger Xdebug breakpoints.

Create inline SVG icons using data URIs

Embed SVG icons inline using data_uri filter: <img src="{{ source(directory ~ '/images/icon.svg')|data_uri('image/svg+xml') }}" />. This eliminates extra HTTP requests for small graphics.

Render entity forms for frontend editing

Display entity edit forms: {{ drupal_entity_form('node', node.id) }}. Create new entity forms with default values: {{ drupal_entity_form('node', values={type: 'article', title: 'New Article'}) }}. Use check_access=false to bypass permission checks when needed.

Access configuration values in templates

Read Drupal configuration directly: {{ drupal_config('system.site', 'name') }} outputs the site name. Useful for displaying settings without preprocess hooks.

Generate conditional links with access checking

Create links that only appear for users with access: {{ drupal_link('Edit'|t, '/node/' ~ node.id ~ '/edit', check_access=true) }}. The link will not render if the user lacks permission.

Tips

  • Use named arguments for optional parameters to improve readability: {{ drupal_entity('block', 'sidebar_block', check_access=false) }}
  • The drupal_view_result() function returns result objects, not the rendered view - use it only for checking if results exist
  • Block plugin IDs can be found using Drush: drush ev "print_r(array_keys(\Drupal::service('plugin.manager.block')->getDefinitions()));"
  • For block content entities, use either drupal_entity('block_content', id) or drupal_block('block_content:<uuid>') - the latter includes block.html.twig wrapper
  • The file_uri and file_url filters support media entities including OEmbed remote media, returning the remote URL for external resources
  • When rendering entities, the check_access parameter defaults to TRUE - set to FALSE only when you've verified access elsewhere
  • drupal_field() does not work with view modes powered by Layout Builder - use the entity's rendered output instead
  • Install symfony/var-dumper for much better output from drupal_dump() and dd() functions
  • Use the with filter as the opposite of core's without filter to add properties: {{ content.field_image|with('#title', 'Photo'|t) }}
  • Cache keys are automatically added by view builders - you generally don't need to manage caching manually

Technical Details

Hooks 3
hook_twig_tweak_functions_alter

Allows modules and themes to add or modify Twig functions provided by Twig Tweak. Functions are added as TwigFunction objects.

hook_twig_tweak_filters_alter

Allows modules and themes to add or modify Twig filters provided by Twig Tweak. Filters are added as TwigFilter objects.

hook_twig_tweak_tests_alter

Allows modules and themes to add custom Twig tests. Tests are added as TwigTest objects.

Drush Commands 2
drush twig-tweak:debug

Lists all Twig functions, filters, and tests available in the current Drupal installation with their signatures. Shows loader paths for template namespaces.

drush twig-tweak:validate

Validates Twig template syntax and outputs any errors found. Can check individual files, directories, or read from STDIN. Alias of twig-tweak:lint.

Security Notes 4
  • The PHP filter (|php) is disabled by default and should remain disabled in production environments due to potential code injection risks
  • When using check_access=false, ensure you have verified user permissions through other means to prevent unauthorized access to content
  • Never expose the $settings['twig_tweak_enable_php_filter'] setting in user-accessible configuration
  • Be cautious with drupal_form() as it renders forms that may perform sensitive operations - ensure proper access control