3

I want the ability to parse environment variables such as {siteName} and globals from channel fields, for example a rich text field.

I have been using {{ include(template_from_string(entry.fieldName)|raw) }}, but this is not suitable because it gives authors the full power of twig. Brandon Kelly pointed out that using the replace filter can work {{ entry.fieldName|replace('{siteName}', siteName)|raw }}

Using a macro I can make this manageable.

I would like the ability to use globals too, what is the best way to have all globals being options to replace or using another method?

Would having 20 possible variable options to replace cause any issues, I would be calling this 3-4 times in a template.

3

You can use my Filter Environment Variables plugin, which will get you about half-way there. It will automatically parse out any environment variables which show up in your dynamic fields...

{{ entry.myField | envvar }}

Once you've got that installed, it's fairly easy to adjust the logic to accommodate for globals as well.

Go to /filterenvvar/twigextensions/FilterEnvVarTwigExtension.php, and change this:

public function envvar($string)
{
    return craft()->config->parseEnvironmentString($string);
}

... to this:

public $globals = array();

public function __construct()
{
    foreach (craft()->globals->allSets as $globalSet)
    {
        foreach ($globalSet->content->attributes as $field => $value)
        {
            $this->globals[$globalSet->handle.'.'.$field] = $value;
        }
    }
}

public function envvar($string)
{
    $string = craft()->config->parseEnvironmentString($string);
    $string = $this->parseGlobals($string);
    return $string;
}

public function parseGlobals($string)
{
    foreach ($this->globals as $key => $value)
    {
        $string = str_replace('{'.$key.'}', $value, $string);
    }

    return $string;
}

This gives you the ability to parse global variables, in addition to your environment variables.

For your global variables, you'll need to include the global set handle in the token name:

my global field value is {globalSetHandle.fieldHandle}

This allows multiple global sets to use the same field.

5
  • 2
    Great work @LindseyD
    – zizther
    Oct 22 '15 at 18:11
  • this works great for global variables, but not working for environment variables. I have tried with single and double curly brackets. Any thoughts?
    – zizther
    Oct 25 '15 at 14:39
  • @zizther: Make sure you use single curly braces, with no padding spaces. Like this: {myVar}
    – Lindsey D
    Oct 25 '15 at 17:33
  • I have tested that way, but it doesn't seem to work. I am trying {siteName} and {basePath}. Example usage {{ entry.title | envvar }}
    – zizther
    Oct 25 '15 at 17:36
  • I tested this answer before posting it, so it should work... DM me on Slack, and we can work through it. We'll post the results back here on this thread for future readers. :)
    – Lindsey D
    Oct 25 '15 at 17:38
2

You could enable your client to use Reference Tags by adding the parseRefs filter.

{% set str = '<p>Since {globalset:42:yearEstablished}</p>' %}
{{ str|parseRefs|raw }}

But this would enable them to access field values of (almost) any element (entries, assets, tags, ..), not just from global sets. And they would also have to remember the global set's ID.

So your current replace filter solution is a good approach in my opinion. You can pass multiple replacements pairs like so (and no, you won't notice if there's 1 or 100 of them):

{% set str = '<p>Since {yearEstablished}</p>' %}
{% set replacements = {
    '{yearEstablished}': companyInfo.yearEstablished,
    '{siteName}': siteName,
} %}
{{ str|replace(replacements)|raw }}

You could also consider building that replacements array programatically.

3
  • thanks. The replace filter is working well and because I am using it multiple times it works great as a macro. How you you see it working programmatically?
    – zizther
    Oct 22 '15 at 17:30
  • Oh, I just meant you could loop through all of a global sets fields to build your array. But doing it manually gives you more fine control, rename things a bit for the client or skip some fields. So if there isn't very many fields it's probably not worth it.
    – carlcs
    Oct 22 '15 at 17:36
  • That is what I had in mind. At the moment there is only 1 environment variable and 2 globals, so works quite well. Programmatically does male sense for manageability though. You could make it work by having a check box to decide whether or not to include it in the filter with another field for a custom name.
    – zizther
    Oct 22 '15 at 17:43
1

With Craft 3 and/or Twig, there is a nice easy way to manage this now.

To output environment variables, config variables, globals, etc you can use {{ view.renderString(entry.richText) }}, the renderString method will parse a template as a string.

There is also Twig's template_from_string() which allows you to parse any text as a Twig template, with access to variables, as well. Compared to renderString it works with include, extends & embed to if you need that

{{ include(template_from_string(entry.richText)) }}

These are both useful cleaner ways than what is discussed above. I have since moved away from the complicated way of having to do it in Craft 2 and used these cleaner methods in Craft 3.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.