Add `block_data()` and `block_export()` functions
Nobody has claimed this yet.
- Dominant language
- PHP
- Stars
- 8.4k
- Forks
- 1.3k
- Avg merge
- 1d 13h
- Merged PRs (30d)
- 37
Description
Description
Currently, Twig's block() function renders a block and returns the result as an HTML string. There is no way to extract structured data from a block.
This becomes a limitation when using Twig Components (<twig:> syntax), where the spread syntax ({{ ...hash }}) requires an associative array, not an HTML string.
Use case: Symfony Form themes with Twig Components
In Symfony's form themes, blocks like widget_attributes and attributes render HTML attribute strings:
<input type="text" {{ block('widget_attributes') }} />
{# outputs: id="name" name="form[name]" required="required" #}
A Twig Component form theme needs the same data as a hash for spread syntax:
<twig:Input type="text" {{ ...block_data('widget_attributes') }} />
Proposal
Add two new Twig functions:
block_export(data)
Called inside a block to export structured data via a side-channel (stored on CoreExtension). The block continues to render HTML normally.
{% block attributes %}
{%- set attrs = {} -%}
{%- for attrname, attrvalue in attr -%}
{%- if attrvalue is same as(true) -%}
{%- set attrs = attrs|merge({(attrname): attrname}) -%}
{%- elseif attrvalue is not same as(false) -%}
{%- set attrs = attrs|merge({(attrname): attrvalue}) -%}
{%- endif -%}
{%- endfor -%}
{%- do block_export(attrs) -%}
{%- for attrname, attrvalue in attrs -%}
{{- ' ' ~ attrname }}="{{ attrvalue }}"
{%- endfor -%}
{% endblock %}
block_data(name)
Renders the block (HTML output is discarded) and returns the data exported via block_export(). Returns [] if the block does not call block_export().
{{ block_data('attributes').id }}
{# returns the structured hash instead of the HTML string #}
Implementation
block_data()uses aparser_callable(likeblock()) to compile to aBlockDataExpressionnodeBlockDataExpressioncompiles to$this->unwrap()->renderBlockData(...)Template::renderBlockData()callsrenderBlock()then returns the exported data fromCoreExtension::getExportedBlockData()- The exported data is consumed on read (reset to
null), preventing leaks between calls
Why not a different approach?
- Returning data from blocks directly: Twig blocks compile to PHP methods with
array $contextpassed by value (variables set inside don't propagate back) - New PHP Twig functions (e.g. in Symfony): would duplicate the logic already in the Twig blocks (translations, boolean normalization), and wouldn't benefit from block inheritance/override
block_data()/block_export(): keeps the logic in one place (the block), works with block inheritance, and is fully backward-compatible (existing blocks continue to render HTML as before)
Related: symfony/symfony#65713
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start from the existing block() parser_callable and compare its behavior with the proposed BlockDataExpression. Trace Template::renderBlockData(), CoreExtension::getExportedBlockData(), and the export-consumption flow. Done means block_data() returns exported data or [] while discarding HTML, block_export() preserves normal rendering, and existing block behavior remains unchanged.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- php
- Domain
- backend
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 68/100