Как получить все переменные из шаблона Twig?

Можно ли получить все переменные внутри шаблона Twig с помощью PHP?

Пример someTemplate.twig.php:

Hello {{ name }}, your new email is {{ email }} 

Теперь я хочу сделать что-то вроде этого:

 $template = $twig->loadTemplate('someTemplate'); $variables = $template->getVariables(); 

$ переменные должны теперь содержать «имя» и «адрес электронной почты».

Причина, по которой я хочу сделать это, – это то, что я работаю над системой CMS, где мои шаблоны и переменные динамической динамики устанавливаются моими пользователями, а также заполняют переменные через API.

Я хочу установить значения по умолчанию для не заданных переменных, и поэтому мне нужен список всех переменных, которые существуют внутри шаблона …

ОБНОВЛЕНИЕ 2017

Это возможно с помощью фильтра {{ dump() }} . Спасибо, что указали это в комментариях!


устаревший

Это невозможно.

Вы можете искать эту переменную в шаблонах ветви и добавлять к ним фильтр по |default('your_value') . Он проверяет, определена ли переменная и не пуста, а если нет – заменит ее на ваше значение.

Это полезно, я нахожу, чтобы получить все ключи верхнего уровня, доступные в текущем контексте:

 <ol> {% for key, value in _context %} <li>{{ key }}</li> {% endfor %} </ol> 

Благодаря https://www.drupal.org/node/1906780

Ответ добавлен в 2015 году

Раньше это было невозможно. Но так как добавлена ​​функция dump () версии 1.5. Таким образом, вы можете получить все переменные из текущего контекста, вызывая dump () без каких-либо параметров:

 <pre> {{ dump(user) }} </pre> 

Тем не менее, вы должны добавить расширение Twig_Extension_Debug явно при создании среды Twig, поскольку dump() по умолчанию недоступен:

 $twig = new Twig_Environment($loader, array( 'debug' => true, // ... )); $twig->addExtension(new Twig_Extension_Debug()); 

Если вы используете что-то вроде Symfony, Silex и т. Д., dump() доступен по умолчанию.

  • Функция Twig

РЕДАКТИРОВАТЬ:

Можно также ссылаться на все переменные, переданные в шаблон (вне контекста dump() ), используя глобальную переменную _context . Это то, что вы искали. Это массив, связывающий все имена переменных с их значениями.

Вы можете найти дополнительную информацию в документации Twig.

Однако для этого конкретного вопроса было бы лучше всего собрать все эти пользовательские переменные, о которых вы говорите, под одной и той же зонтичной переменной, так что их получение не будет головной болью. Я бы стал массивом, называемым custom_variables или любым custom_variables .

Если вам нужны все элементы Twig внутри текста, просто используйте:

 preg_match_all('/\{\%\s*(.*)\s*\%\}|\{\{(?!%)\s*((?:[^\s])*)\s*(?<!%)\}\}/i', $text, $matches); 

У меня возникла проблема, когда редактор WSIWYG размещал теги HTML внутри переменных Twig. Я их фильтрую с помощью:

 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; } 

ОБНОВИТЬ

Используйте это выражение, чтобы найти все {{}} и {%%}

 preg_match_all('/\{\%\s*([^\%\}]*)\s*\%\}|\{\{\s*([^\}\}]*)\s*\}\}/i', $text, $matches); 

Вот лучший способ и самый простой способ сбрасывать все переменные:

 {{ dump () }} 

Источник: https://www.drupal.org/docs/8/theming/twig/discovering-and-inspecting-variables-in-twig-templates

После использования ответа Дункана в течение некоторого времени я наконец нашел «правильный» способ сбрасывать все переменные завихрения шаблона

 {% dump %} 

Это все. Все переменные, доступные в шаблоне, будут сброшены и в разделе дампа профилировщика, а не в середине вашего html, как с {{dump ()}}

если вы поместите содержимое дампа () в переменную

 {% set d = dump() %} 

вы получите все переменные, но в «dump ready» html, поэтому было бы болью проанализировать его

надеюсь, это поможет

Я думаю, что ответ 19Gerhard85 довольно хорош, хотя для этого может потребоваться некоторая настройка, потому что он подходит для некоторых пустых строк для меня. Мне нравится использовать существующие функции там, где это возможно, и это подход, в основном используемый функциями твига. Вам нужно получить доступ к среде твинов вашего приложения.

 /** * @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); } 

И единственной пользовательской частью этого является рекурсивная функция для сбора только определенных типов узлов:

 /** * @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 } } } 

Вы должны проанализировать шаблон и пройти через AST, который он возвращает:

 $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; } 

После того, как я провел довольно много времени, пробовав все вышеперечисленные ответы, я понял, по какой-то неожиданной причине, регулярные выражения не работали вообще с моими простыми шаблонами. Они вернули хлам или частичную информацию. Поэтому я решил пойти, удалив все содержимое между тегами, а не подсчитывая теги ^ _ ^.

Я имею в виду, что если шаблон является 'AAA {{BB}} CC {{DD}} {{BB}} SS' , я просто добавляю '}}' в начале шаблона и '{{ в конце .. .. и весь контент между }} и {{ я просто вычеркнутый, добавив запятую между => }}{{BB,}}{{DD,}}{{BB,}}{{ . Затем – просто стереть }} и {{ .

Мне потребовалось около 15 минут, чтобы писать и тестировать … но с регулярными выражениями я потратил около 5 часов без успеха.

 /** * 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)); 

Надеюсь, это поможет кому-то 🙂

То, как я это делаю, это

 <script>console.log({{ _context | json_encode | raw }});</script> 

И тогда я просто проверяю консоль с помощью DevTools

Создайте Twig_Extension и добавьте функцию с флагом 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 ''; } } 

Контекст будет передан как первый параметр вашей функции, содержащий все переменные.

На вашем шаблоне Twig вам просто нужно вызвать эту функцию:

 {{myTwigFunction()}} 

Если вам нужна помощь в создании расширения Twig, обратитесь к этой документации:

http://twig.sensiolabs.org/doc/2.x/advanced.html

У этого вопроса есть вопрос – там я нашел полезный и более мощный RegEX, чем выше. Этот, я улучшил, чтобы соответствовать более точно:

 \{\{(?!%)\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.