The problem
Twig context is never stored in the template object, so this will be very difficult to find a clean way to achieve this. For example, the following Twig code:
{% set test = 'Hello, world' %}
Will compile to:
<?php
class __TwigTemplate_20df0122e7c88760565e671dea7b7d68c33516f833acc39288f926e234b08380 extends Twig_Template
{
/* ... */
protected function doDisplay(array $context, array $blocks = array())
{
// line 1
$context["test"] = "Hello, world";
}
/* ... */
}
As you can see, the inherited context is not passed to the doDisplay method by reference, and is never stored in the object itself (like $this->context = $context
). This deisgn allow templates to be reusable, and is memory-friendly.
Solution 1 : using global variables
I don't know if you are aware of Global Variables in Twig. You can do a bunch of hacks with them.
The easiest usage is to load all your globals inside your twig environment.
$loader = new Twig_Loader_Filesystem(__DIR__.'/view');
$env = new Twig_Environment($loader);
$env->addGlobal('foo', 'bar');
$env->addGlobal('Hello', 'world!');
Then, you can use {{ foo }}
and {{ Hello }}
in your whole application.
But there are 2 problems here:
As you're trying to load variables from twig files, I assume you have lots of variables to initialize depending on your feature and don't want to load everything all time.
you are loading variables from PHP scripts and not from Twig, and your question want to import variables from a twig file.
Solution 2 : using a Twig extension
You can also create a storage extension that provide a save
function to persist some template's context somewhere, and a restore
function to merge this stored context in another one.
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';
}
}
/* usage example */
$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 }}
Note: if you only want to import variables without actually rendering what's inside twig/variables.twig, you can also use:
{% set tmp = include('variables.twig') %}
{{ restore('test') }}
{{ foo }}
Final note
I'm not used to the JavaScript twig port, but it looks like you can still extend it, that's your go :)