Is it possible to retrieve all variables inside a Twig template with PHP?
Example someTemplate.twig.php:
Hello {{ name }},
your new email is {{ ema
The way I do it is
<script>console.log({{ _context | json_encode | raw }});</script>
And then I just check my console using DevTools
I built a Twig2Schema class to infer variables from a Twig AST. To get the variables in a document, you need to recursively "walk" through the Twig AST and have rules in place when you encounter certain types of language nodes.
This class extracts variable names from Nodes if they are not always defined, and also grabs variables from the value used in ForLoopNodes and IfStatements.
To use it, you can either call infer
for the whole template, or a subset of the tree using inferFromAst
.
<?php
class Twig2Schema
{
/**
* @param \Twig\Environment $twig - A twig environment containing loaded templates
* @param $twigTemplateName - The name of the template to infer variables from
* @param $config - A configuration object for this function
* @return array
*/
public function infer(\Twig\Environment $twig, $twigTemplateName)
{
$source = $twig->getLoader()->getSourceContext($twigTemplateName);
$tokens = $twig->tokenize($source);
$ast = $twig->parse($tokens);
return $this->inferFromAst($ast);
}
/**
* @param \Twig\Node\ModuleNode $ast - An abstract syntax tree parsed from Twig
* @return array - The variables used in the Twig template
*/
public function inferFromAst(\Twig\Node\ModuleNode $ast)
{
$keys = $this->visit($ast);
foreach ($keys as $key => $value) {
if ($value['always_defined'] || $key === '_self') {
unset($keys[$key]);
}
}
return $keys;
}
/**
* @param \Twig\Node\Node $ast - The tree to traverse and extract variables
* @return array - The variables found in this tree
*/
private function visit(\Twig\Node\Node $ast)
{
$vars = [];
switch (get_class($ast)) {
case \Twig\Node\Expression\AssignNameExpression::class:
case \Twig\Node\Expression\NameExpression::class:
$vars[$ast->getAttribute('name')] = [
'type' => get_class($ast),
'always_defined' => $ast->getAttribute('always_defined'),
'is_defined_test' => $ast->getAttribute('is_defined_test'),
'ignore_strict_check' => $ast->getAttribute('ignore_strict_check')
];
break;
case \Twig\Node\ForNode::class:
foreach ($ast as $key => $node) {
switch ($key) {
case 'value_target':
$vars[$node->getAttribute('name')] = [
'for_loop_target' => true,
'always_defined' => $node->getAttribute('always_defined')
];
break;
case 'body':
$vars = array_merge($vars, $this->visit($node));
break;
default:
break;
}
}
break;
case \Twig\Node\IfNode::class:
foreach ($ast->getNode('tests') as $key => $test) {
$vars = array_merge($vars, $this->visit($test));
}
foreach ($ast->getNode('else') as $key => $else) {
$vars = array_merge($vars, $this->visit($else));
}
break;
default:
if ($ast->count()) {
foreach ($ast as $key => $node) {
$vars = array_merge($vars, $this->visit($node));
}
}
break;
}
return $vars;
}
}
UPDATE 2019
Although {{ dump() }}
does work, in some circumstances it may result in a "memory exhausted" error from PHP if it generates too much information (for example, due to recursion). In this case, try {{ dump(_context|keys) }}
to get a list of the defined variables by name without dumping their contents.
UPDATE 2017
It is possible by using {{ dump() }}
filter. Thanks for pointing that out in the comments!
OUTDATED
It is not possible.
You can look for these variable in twig templates and add |default('your_value')
filter to them. It will check if variable is defined and is not empty, and if no - will replace it with your value.
This is useful I find to get all the top-level keys available in the current context:
<ol>
{% for key, value in _context %}
<li>{{ key }}</li>
{% endfor %}
</ol>
Thanks to https://www.drupal.org/node/1906780
In the past it wasn't possible. But since version 1.5 dump() function has added. So you can get all variables from current context calling dump() without any parameters:
<pre>
{{ dump(user) }}
</pre>
However, you must add the Twig_Extension_Debug extension explicitly when creating your Twig environment because dump()
isn't available by default:
$twig = new Twig_Environment($loader, array(
'debug' => true,
// ...
));
$twig->addExtension(new Twig_Extension_Debug());
If you have been using something like Symfony, Silex, etc, dump()
is available by default.
One can also reference all variables passed to a template (outside the context of dump()
), using the global variable _context
. This is what you were looking for. It is an array associating all variable names to their values.
You can find some additional info in the Twig documentation.
For this specific question however, it would probably be best to gather all of these custom variables you are speaking of, under a same umbrella variable, so that retrieving them would not be a headache. I would be an array called custom_variables
or whatever.
After using duncan's answer for quite some time I finally found the "right" way to dump all twig variables of a template:
{% dump %}
That's it. All the variables available in the template will be dumped and in the dump section of the profiler, not in the middle of your html like with {{ dump() }}
.
if you put the contents of dump()
into a variable:
{% set d = dump() %}
you 'll get all the variables but in "dump ready" html so it would be a pain to parse it.
Hope that helps.