问题
Twig上下文永远不会存储在模板对象中,因此要找到一种清洁的方法实现这一点将会非常困难。例如,以下Twig代码:
{% set test = 'Hello, world' %}
将编译为:
<?php
class __TwigTemplate_20df0122e7c88760565e671dea7b7d68c33516f833acc39288f926e234b08380 extends Twig_Template
{
protected function doDisplay(array $context, array $blocks = array())
{
$context["test"] = "Hello, world";
}
}
正如您所看到的,继承的上下文并没有通过引用传递给doDisplay方法,并且从未存储在对象本身中(例如$this->context = $context
)。这种设计允许模板可重用,并且对内存友好。
解决方案1:使用全局变量
我不知道您是否了解Twig中的全局变量。您可以使用它们进行一堆黑客攻击。
最简单的用法是在twig环境中加载所有全局变量。
$loader = new Twig_Loader_Filesystem(__DIR__.'/view');
$env = new Twig_Environment($loader);
$env->addGlobal('foo', 'bar');
$env->addGlobal('Hello', 'world!');
接下来,您可以在整个应用程序中使用{{ foo }}
和{{ Hello }}
。
但是这里有两个问题:
解决方案2:使用Twig扩展
您还可以创建一个存储扩展,提供一个save
函数以将某些模板上下文持久化到某个位置,并提供一个restore
函数以将此存储的上下文合并到另一个上下文中。
proof_of_concept.php
<?php
require __DIR__.'/vendor/autoload.php';
class StorageTwigExtension extends Twig_Extension
{
protected $storage = [];
public function getFunctions() {
return [
new Twig_SimpleFunction('save', [$this, 'save'], ['needs_context' => true]),
new Twig_SimpleFunction('restore', [$this, 'restore'], ['needs_context' => true]),
];
}
public function save($context, $name) {
$this->storage = array_merge($this->storage, $context);
}
public function restore(&$context, $name) {
$context = array_merge($context, $this->storage);
}
public function getName() {
return 'storage';
}
}
$loader = new Twig_Loader_Filesystem(__DIR__.'/view');
$env = new Twig_Environment($loader);
$env->addExtension(new StorageTwigExtension());
echo $env->render('test.twig'), PHP_EOL;
twig/variables.twig
{% set foo = 'bar' %}
{% set Hello = 'world!' %}
{{ save('test') }}
twig/test.twig
{% include 'variables.twig' %}
{{ restore('test') }}
{{ foo }}
注意:如果你只想导入变量而不实际呈现
twig/variables.twig 中的内容,你也可以使用以下代码:
{% set tmp = include('variables.twig') %}
{{ restore('test') }}
{{ foo }}
最后说明
我不太熟悉JavaScript twig端口,但看起来你仍然可以扩展它,这是你的目标 :)