php - formato - twig array
¿Cómo recuperar todas las variables de una plantilla Twig? (13)
Respuesta agregada en 2015
En el pasado no fue posible. Pero desde la versión 1.5 se ha agregado la función dump() . De modo que puede obtener todas las variables del volcado de llamadas al contexto actual () sin ningún parámetro:
<pre>
{{ dump(user) }}
</pre>
Sin embargo, debe agregar la extensión Twig_Extension_Debug explícitamente al crear su entorno Twig porque dump()
no está disponible de manera predeterminada:
$twig = new Twig_Environment($loader, array(
''debug'' => true,
// ...
));
$twig->addExtension(new Twig_Extension_Debug());
Si ha estado usando algo como Symfony, Silex, etc., dump()
está disponible de forma predeterminada.
EDITAR:
También se puede hacer referencia a todas las variables pasadas a una plantilla (fuera del contexto de dump()
), usando la variable global _context
. Esto es lo que estabas buscando. Es una matriz que asocia todos los nombres de variables a sus valores.
Puede encontrar información adicional en la documentación de Twig.
Sin embargo, para esta pregunta específica, probablemente sería mejor recopilar todas estas variables personalizadas de las que está hablando, bajo una misma variable paraguas, de modo que recuperarlas no sería un dolor de cabeza. Sería una matriz llamada custom_variables
o lo que sea.
¿Es posible recuperar todas las variables dentro de una plantilla de Twig con PHP?
Ejemplo someTemplate.twig.php:
Hello {{ name }},
your new email is {{ email }}
Ahora quiero hacer algo como esto:
$template = $twig->loadTemplate(''someTemplate'');
$variables = $template->getVariables();
$ variables ahora deberían contener "nombre" y "correo electrónico".
La razón por la que quiero hacer esto es porque estoy trabajando en un sistema CMS donde mis plantillas y variables twig son establecidas dinámicamente por mis usuarios y también llenan las variables a través de una API.
Quiero establecer valores predeterminados para variables no establecidas y, por lo tanto, necesito una lista de todas las variables que existen dentro de la plantilla ...
Aquí está la mejor manera y la manera más fácil de volcar todas las variables:
{{ dump () }}
Fuente: https://www.drupal.org/docs/8/theming/twig/discovering-and-inspecting-variables-in-twig-templates
Cree una Twig_Extension y agregue una función con el indicador needs_context :
class MyTwigExtension extends Twig_Extension{
public function getFunctions()
{
return array(
new /Twig_SimpleFunction(''myTwigFunction'', array($this, ''myTwigFunction''), array(''needs_context'' => true)),
);
}
public function myTwigFunction($context)
{
var_dump($context);
return '''';
}
}
El contexto pasará como el primer parámetro de su función, que contiene todas las variables.
En su plantilla Twig solo tiene que llamar a esa función:
{{myTwigFunction()}}
Si necesita ayuda para crear una extensión de Twig, consulte esta documentación:
Creo que la respuesta de 19Gerhard85 es bastante buena, aunque podría necesitar algunos ajustes, ya que combinó algunas cuerdas vacías para mí. Me gusta utilizar las funciones existentes siempre que sea posible y este es un enfoque que utiliza principalmente las funciones de twig. Necesita acceder al entorno twig de su aplicación.
/**
* @param $twigTemplateName
* @return array
*/
public function getRequiredKeys($twigTemplateName)
{
$twig = $this->twig;
$source = $twig->getLoader()->getSource($twigTemplateName);
$tokens = $twig->tokenize($source);
$parsed = $twig->getParser()->parse($tokens);
$collected = [];
$this->collectNodes($parsed, $collected);
return array_keys($collected);
}
Y la única parte personalizada es la función recursiva para recopilar solo ciertos tipos de nodos:
/**
* @param /Twig_Node[] $nodes
* @param array $collected
*/
private function collectNodes($nodes, array &$collected)
{
foreach ($nodes as $node) {
$childNodes = $node->getIterator()->getArrayCopy();
if (!empty($childNodes)) {
$this->collectNodes($childNodes, $collected); // recursion
} elseif ($node instanceof /Twig_Node_Expression_Name) {
$name = $node->getAttribute(''name'');
$collected[$name] = $node; // ensure unique values
}
}
}
Debes analizar la plantilla y recorrer el AST que devuelve:
$loaded = $twig->getLoader()->getSource($template);
var_dump(extractVars($twig->parse($twig->tokenize($loaded)));
function extractVars($node)
{
if (!$node instanceof Traversable) return array();
$vars = array();
foreach ($node as $cur)
{
if (get_class($cur) != ''Twig_Node_Expression_Name'')
{
$vars = array_merge($vars, extractVars($cur));
}
else
{
$vars[] = $cur->getAttribute(''name'');
}
}
return $vars;
}
Después de pasar toda la noche probando todas las respuestas anteriores, me di cuenta, por alguna razón inesperada, que las expresiones regulares no funcionaban en absoluto con mis plantillas simples. Devolvieron información incompleta o parcial. Así que decidí ir borrando todo el contenido entre etiquetas en lugar de contar las etiquetas ^ _ ^.
Quiero decir, si una plantilla es ''AAA {{BB}} CC {{DD}} {{BB}} SS''
, simplemente agregué ''}}''
al principio de la plantilla y ''{{
al final ... .. y todo el contenido entre }}
y {{
Me voy a despojar, agregando una coma entre => }}{{BB,}}{{DD,}}{{BB,}}{{
. Entonces, simplemente borre }}
y {{
.
Me tomó alrededor de 15 minutos escribir y probar ... pero con expresiones regulares he gastado alrededor de 5 horas sin éxito.
/**
* deletes ALL the string contents between all the designated characters
* @param $start - pattern start
* @param $end - pattern end
* @param $string - input string,
* @return mixed - string
*/
function auxDeleteAllBetween($start, $end, $string) {
// it helps to assembte comma dilimited strings
$string = strtr($start. $string . $end, array($start => '',''.$start, $end => chr(2)));
$startPos = 0;
$endPos = strlen($string);
while( $startPos !== false && $endPos !== false){
$startPos = strpos($string, $start);
$endPos = strpos($string, $end);
if ($startPos === false || $endPos === false) {
return $string;
}
$textToDelete = substr($string, $startPos, ($endPos + strlen($end)) - $startPos);
$string = str_replace($textToDelete, '''', $string);
}
return $string;
}
/**
* This function is intended to replace
* //preg_match_all(''//{/%/s*([^/%/}]*)/s*/%/}|/{/{/s*([^/}/}]*)/s*/}/}/i'',
* which did not give intended results for some reason.
*
* @param $inputTpl
* @return array
*/
private function auxGetAllTags($inputTpl){
$inputTpl = strtr($inputTpl, array(''}}'' => '',''.chr(1), ''{{'' => chr(2)));
return explode('','',$this->auxDeleteAllBetween(chr(1),chr(2),$inputTpl));
}
$template = ''<style>
td{border-bottom:1px solid #eee;}</style>
<p>Dear {{jedi}},<br>New {{padawan}} is waiting for your approval: </p>
<table border="0">
<tbody><tr><td><strong>Register as</strong></td><td>{{register_as}}, user-{{level}}</td></tr>
<tr><td><strong>Name</strong></td><td>{{first_name}} {{last_name}}</td></tr>...'';
print_r($this->auxGetAllTags($template));
Espero que ayude a alguien :)
Después de usar la respuesta de duncan durante bastante tiempo, finalmente encontré la forma "correcta" de volcar todas las variables de ramita de una plantilla
{% dump %}
Eso es todo. Se descargarán todas las variables disponibles en la plantilla y en la sección volcado del generador de perfiles, no en el medio de su html como con {{dump ()}}
si pones el contenido de dump () en variable
{% set d = dump() %}
obtendrás todas las variables pero en html "dump ready" así que sería un dolor analizarlo
Espero que ayude
Esta pregunta tiene una doble explicación : allí encontré un RegEX útil y más poderoso que el anterior. Este, he mejorado para que coincida con más precisión:
/{/{(?!%)/s* # Starts with {{ not followed by % followed by 0 or more spaces
((?:(?!/.)[^/s])*?) # Match anything without a point or space in it
(/|(?:(?!/.)[^/s])*)? # Match filter within variable
/s*(?<!%)/}/} # Ends with 0 or more spaces not followed by % ending with }}
| # Or
/{%/s* # Starts with {% followed by 0 or more spaces
(?:/s(?!endfor)|(endif)|(else)(/w+))+ # Match the last word which can not be endfor, endif or else
/s*%/} # Ends with 0 or more spaces followed by %}
# Flags: i: case insensitive matching | x: Turn on free-spacing mode to ignore whitespace between regex tokens, and allow # comments.
Esto es útil para obtener todas las claves de nivel superior disponibles en el contexto actual:
<ol>
{% for key, value in _context %}
<li>{{ key }}</li>
{% endfor %}
</ol>
Gracias a https://www.drupal.org/node/1906780
La forma en que lo hago es
<script>console.log({{ _context | json_encode | raw }});</script>
Y luego solo controlo mi consola usando DevTools
Si necesita todos los elementos de Twig dentro de un texto, simplemente use:
preg_match_all(''//{/%/s*(.*)/s*/%/}|/{/{(?!%)/s*((?:[^/s])*)/s*(?<!%)/}/}/i'', $text, $matches);
Tuve un problema donde el editor WSIWYG colocaba etiquetas HTML dentro de las variables de Twig. Los filtro con:
public function cleanHTML($text)
{
preg_match_all(''//{/%/s*(.*)/s*/%/}|/{/{(?!%)/s*((?:[^/s])*)/s*(?<!%)/}/}/i'', $text, $matches);
if (isset($matches[0]) && count($matches[0])) {
foreach ($matches[0] as $match) {
$clean_match = strip_tags($match);
$text = str_replace($match, $clean_match, $text);
}
}
return $text;
}
ACTUALIZAR
Usa esta expresión para encontrar todos {{}} y {%%}
preg_match_all(''//{/%/s*([^/%/}]*)/s*/%/}|/{/{/s*([^/}/}]*)/s*/}/}/i'', $text, $matches);
ACTUALIZACIÓN 2017
Es posible usando el filtro {{ dump() }}
. ¡Gracias por señalar eso en los comentarios!
ANTICUADO
No es posible.
Puede buscar estas variables en plantillas |default(''your_value'')
filtro |default(''your_value'')
. Verificará si la variable está definida y no está vacía, y si no, la reemplazará con su valor.
$loader1 = new Twig_Loader_Array([
''blub.html'' => ''{{ twig.template.code }}'',
]);
$twig = new Twig_Environment($loader1);
$tokens = $twig->tokenize($loader1->getSource(''blub.html''));
$nodes = $twig->getParser()->parse($tokens);
var_dump($this->getTwigVariableNames($nodes));
function getTwigVariableNames($nodes): array
{
$variables = [];
foreach ($nodes as $node) {
if ($node instanceof /Twig_Node_Expression_Name) {
$name = $node->getAttribute(''name'');
$variables[$name] = $name;
} elseif ($node instanceof /Twig_Node_Expression_Constant && $nodes instanceof /Twig_Node_Expression_GetAttr) {
$value = $node->getAttribute(''value'');
if (!empty($value) && is_string($value)) {
$variables[$value] = $value;
}
} elseif ($node instanceof /Twig_Node_Expression_GetAttr) {
$path = implode(''.'', $this->getTwigVariableNames($node));
if (!empty($path)) {
$variables[$path] = $path;
}
} elseif ($node instanceof /Twig_Node) {
$variables += $this->getTwigVariableNames($node);
}
}
return $variables;
}
que te diviertas :-)