Можно ли получить значение переменной ветки в расширении

Я модернизирую устаревшее приложение, используя компоненты Symfony2.
Я пытался (и в основном не получилось) заменить старые шаблоны php ветками.

Часть, с которой я борюсь, состоит в следующем: каждый подшаблон имеет свой собственный класс, содержащий свою собственную логику (Сказал, что это все о наследии).

Итак, я создал расширение ветки, которое вызывает класс шаблона, а затем включает в себя суб-шаблон, передавая ему переменные, определенные классом (Вот код расширения).

например:

{% template "NavBlockTemplate" %}
  • Создает новый NavBlockTemplate пример.
    • звонки getTemplateName чтобы получить файл шаблона ветки для включения
    • звонки getVariables чтобы получить переменные, необходимые для шаблона
    • создает Twig_Node_Include указанного шаблона с данными переменными

Грустная часть здесь такова: каждый шаблон может передавать переменные в свой конструктор подшаблонов …

Итак, что мне нужно, но не уверен, что это вообще возможно, это что-то вроде:

{% template "NavBlockTemplate" with { 'varName': value, 'var_id': otherVar.id }
  • Компилирует с переменными из Twig_Expression объекты в php vars
  • Создает новый NavBlockTemplate экземпляр с php компилирует vars
    • звонки getTemplateName чтобы получить файл шаблона ветки для включения
    • звонки getVariables чтобы получить переменные, необходимые для шаблона
    • создает Twig_Node_Include указанного шаблона с данными переменными

Так это возможно? Любые советы о том, как этого добиться?

2

Решение

Значения переменных не могут быть доступны во время компиляции шаблона. Они еще не доступны.
Twig имеет 2 отдельных фазы, когда вы звоните render($name, $context):

  • сначала компилирует шаблон (если он еще не доступен в кеше)
  • во-вторых, это делает это.

2 шага легко увидеть при реализации Twig_Environment::render():

public function render($name, array $context = array())
{
return $this->loadTemplate($name)->render($context);
}

Ваш пользовательский тег должен учитывать это. Потребуется создать специальный класс узлов, который будет скомпилирован в необходимую логику. Вы можете посмотреть, как реализованы существующие теги Twig.
Даже имя класса, которое вы включаете, может быть доступно во время компиляции, как и вы. $expr->getAttribute('value') будет работать, только если выражение является константным выражением, и вы не применяете его в своем парсере.

С другой стороны, использование тега в этом случае, вероятно, не лучшее решение (хотя и самое сложное). Согласно семантике Twig, функция была бы лучше. Именно поэтому Twig также ввел include() функция как она подходит лучше. Вот как это будет выглядеть.

в шаблоне:

{{ include_legacy("NavBlockTemplate", { 'varName': value, 'var_id': otherVar.id }) }}

в расширении:

class LegacyIncludeExtension extends \TwigExtension
{

public function getFunctions()
{
return array(
new \Twig_SimpleFunction(
'include_legacy',
array($this, 'includeLegacy'),
array('is_safe' => array('all'), 'needs_environment' => true, 'needs_context' => true)
),
);
}

public function includeLegacy(\Twig_Environment $env, array $context, $name, array $variables = array())
{
$fqcn = // determine the class name

$instance = new fqcn();

$template = $instance->getTemplateName();
$variables = array_merge($instance->getVariables(), $variables);

return $env->resolveTemplate($template)->render(array_merge($context, $variables));
}
}

Последняя строка метода выполняет основную работу twig_include. Если вам нужна поддержка для выделения контекста, это довольно просто (сделайте объединение массива шаблона условным). Поддержка ignore_missing — это больше работы, и вам было бы лучше звонить twig_include непосредственно в таком случае:

    public function includeLegacy(\Twig_Environment $env, array $context, $name, array $variables = array(), $withContext = true, $ignoreMissing = false)
{
$fqcn = // determine the class name

$instance = new fqcn();

$template = $instance->getTemplateName();
$variables = array_merge($instance->getVariables(), $variables)

return twig_include($env, $context, $template, $variables, $withContext, $ignoreMissing);
}
1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]