<p><strong>Edit:</strong> I needed to do a little digging.</p>

<p>Internally, Craft can actually have multiple instances of <a href="http://twig.sensiolabs.org/api/master/Twig_Environment.html" rel="noreferrer">Twig_Environment</a> running (a Twig_Environment instance is what you get back by calling <code>craft()-&gt;templates-&gt;getTwig()</code>). <a href="https://github.com/pixelandtonic/Craft-Release/blob/master/app/services/TemplatesService.php#L165" rel="noreferrer">Craft caches each instance in a private class variable</a>, with the template loader classname and a hash of the environment's options making up the cache key. If a Twig_Environment instance doesn't exist for the loader classname and options array you pass to <code>getTwig()</code> (<code>null</code> and <code>null</code>, in your case), Craft will actually create a new Twig_Environment instance and return it.</p>

<p>This means that you're probably not getting back the same Twig_Environment instance that Craft is using to actually render your template – which explains why the call to <code>addGlobal()</code> works, but the variable is still undefined in your template.</p>

<p>The solution is to make sure to pass in the same loader classname and options as Craft does, to make the TemplateService return the same instance. The default here appears to be <code>null</code> for the loader classname, and <code>['safe_mode' =&gt; false]</code> for the options.</p>

<p>In other words, this should work:</p>

<pre><code>public function init()
{
    $var = 'something';
    $twig = craft()-&gt;templates-&gt;getTwig(null, ['safe_mode' =&gt; false]);
    $twig-&gt;addGlobal('var', $var);
}
</code></pre>

<p>Unfortunately, I don't know if Craft can ever be expected to use different options (or even a different loader) in certain circumstances – e.g. if <code>safe_mode</code> would ever be <code>true</code>. In any case, it is <code>false</code> by default in the TemplatesService <a href="https://github.com/pixelandtonic/Craft-Release/blob/master/app/services/TemplatesService.php#L244" rel="noreferrer"><code>render()</code></a> method. Hopefully, someone might clear this up further.</p>

<p><strong>Anyway – for a less hacky way to add globals to the Twig environment, here's my original answer:</strong></p>

<p>You'll need to <a href="https://cameronspear.com/blog/craft-cms-twig-filter-extension/" rel="noreferrer">create a custom Twig extension</a>. In your extension class, add a <code>getGlobals()</code> method, e.g.</p>

<pre><code>&lt;?php namespace Craft;

use Twig_Extension;  
use Twig_Filter_Method;

class AwesomeTwigExtension extends \Twig_Extension  
{
    public function getName()
    {
        return 'Awesome';
    }
    public function getGlobals()
    {
        $var = 'something';
        return [
            'var' =&gt; $var,
        ];
    }
}
</code></pre>

<p>Don't forget to actually load your custom extension – in your plugin's primary class:</p>

<pre><code>public function addTwigExtension()
{
    Craft::import('plugins.pluginhandle.twigextensions.AwesomeTwigExtension');
    return new AwesomeTwigExtension();
}
</code></pre>

<p>Of course, adding the globals in a custom extension instead of just using your plugin's primary class' <code>init()</code> method is a bit more verbose, but remember that you could easily add a method to your plugin's primary class returning the globals and just call that from your extension, e.g.</p>

<pre><code>// In your plugin's primary class
public function getGlobals()
{
    $var = ...
    return [
        'var' =&gt; $var,
        ...
    ];
}

// In your custom Twig extension
public function getGlobals()
{
    return craft()-&gt;plugins-&gt;getPlugin('pluginHandle')-&gt;getGlobals();
}
</code></pre>

<p>(You could of course also return the globals from a plugin <a href="https://craftcms.com/docs/plugins/services" rel="noreferrer">service</a>, which would be cleaner).</p>

<p>Hopefully somebody else will have an explanation for why the <code>addGlobal()</code> method doesn't work – and perhaps an even easier solution.</p>

CC BY-SA 3.0
2016-08-24T12:53:22.180Z
Wow, now that's a comprehensive answer! Thank you for going into so much detail Mats. It would appear the 'less hacky' approach you mentioned is how I've been doing it already. I'm going to mark this as correct, because you have explained and demonstrated that getGlobal does exist and can be used, albeit with a few caveats. Thanks again, much appreciated.
Mark Notton
CC BY-SA 3.0
2016-08-24T13:01:44.500Z
No worries, @MarkNotton - good to know it proved worthwhile.
Mats Mikkel Rummelhoff
CC BY-SA 3.0
2016-08-24T11:02:38.217Z
2016-08-24T11:32:46.323Z
2016-08-24T11:32:46.323Z
Mats Mikkel Rummelhoff
<p>I know Craft gives us access to <a href="https://craftcms.com/classreference/services/TemplatesService#getTwig-detail" rel="nofollow noreferrer">Twigs getTwig template service</a>; so when I attempt to use the <a href="http://twig.sensiolabs.org/doc/advanced.html#globals" rel="nofollow noreferrer">addGlobal</a> function like so:</p>
<pre><code>craft()-&gt;templates-&gt;getTwig()-&gt;addGlobal('var', $var);
</code></pre>
<p>... nothing happens. No errors. I had hoped putting this in my plugins <code>init()</code> would allow me to call the variable in a twig template like so: <code>{{ var }}</code>. But that just returns an error.</p>
<blockquote>
<p>Variable &quot;var&quot; does not exist</p>
</blockquote>
<p>I know of <a href="https://craftcms.stackexchange.com/a/7088/584">other methods to define global variables</a>. I just wondered where I was going wrong with that quick one-liner that doesn't seem to work.</p>
<p>Maybe Craft has ommitted it?</p>
<p>Thanks,</p>
<p>Mark</p>

<plugin-development><variable><globals>
Does Twigs 'addGlobal' exist in Craft?
# Does Twigs 'addGlobal' exist in Craft?

(Asked by: username_0 on 2016-08-24)

I know Craft gives us access to Twigs getTwig template service; so when I attempt to use the addGlobal function like so:
craft()->templates->getTwig()->addGlobal('var', $var);

... nothing happens. No errors. I had hoped putting this in my plugins init() would allow me to call the variable in a twig template like so: {{ var }}. But that just returns an error.

Variable "var" does not exist

I know of other methods to define global variables. I just wondered where I was going wrong with that quick one-liner that doesn't seem to work.
Maybe Craft has ommitted it?
Thanks,
Mark

**Tags:** plugin-development, variable, globals

---

## 1 answers

### Answer by username_1 on 2016-08-24. Score: 7 | Accepted answer

Edit: I needed to do a little digging.
Internally, Craft can actually have multiple instances of Twig_Environment running (a Twig_Environment instance is what you get back by calling craft()->templates->getTwig()). Craft caches each instance in a private class variable, with the template loader classname and a hash of the environment's options making up the cache key. If a Twig_Environment instance doesn't exist for the loader classname and options array you pass to getTwig() (null and null, in your case), Craft will actually create a new Twig_Environment instance and return it.
This means that you're probably not getting back the same Twig_Environment instance that Craft is using to actually render your template – which explains why the call to addGlobal() works, but the variable is still undefined in your template.
The solution is to make sure to pass in the same loader classname and options as Craft does, to make the TemplateService return the same instance. The default here appears to be null for the loader classname, and ['safe_mode' => false] for the options.
In other words, this should work:
public function init()
{
    $var = 'something';
    $twig = craft()->templates->getTwig(null, ['safe_mode' => false]);
    $twig->addGlobal('var', $var);
}

Unfortunately, I don't know if Craft can ever be expected to use different options (or even a different loader) in certain circumstances – e.g. if safe_mode would ever be true. In any case, it is false by default in the TemplatesService render() method. Hopefully, someone might clear this up further.
Anyway – for a less hacky way to add globals to the Twig environment, here's my original answer:
You'll need to create a custom Twig extension. In your extension class, add a getGlobals() method, e.g.
 $var,
        ];
    }
}

Don't forget to actually load your custom extension – in your plugin's primary class:
public function addTwigExtension()
{
    Craft::import('plugins.pluginhandle.twigextensions.AwesomeTwigExtension');
    return new AwesomeTwigExtension();
}

Of course, adding the globals in a custom extension instead of just using your plugin's primary class' init() method is a bit more verbose, but remember that you could easily add a method to your plugin's primary class returning the globals and just call that from your extension, e.g.
// In your plugin's primary class
public function getGlobals()
{
    $var = ...
    return [
        'var' => $var,
        ...
    ];
}

// In your custom Twig extension
public function getGlobals()
{
    return craft()->plugins->getPlugin('pluginHandle')->getGlobals();
}

(You could of course also return the globals from a plugin service, which would be cleaner).
Hopefully somebody else will have an explanation for why the addGlobal() method doesn't work – and perhaps an even easier solution.

> **Comments:**
> **username_0**: Wow, now that's a comprehensive answer! Thank you for going into so much detail Mats. It would appear the 'less hacky' approach you mentioned is how I've been doing it already. I'm going to mark this as correct, because you have explained and demonstrated that getGlobal does exist and can be used, albeit with a few caveats. Thanks again, much appreciated.  
> **username_1**: No worries, @MarkNotton - good to know it proved worthwhile.  

---

