Iterate over Keys and Values in Twig with Timber

I found the Twig documentation for using key value pairs from PHP arrays a little sparse, so thought I’d elaborate.

,

I found the Twig documentation for using key value pairs from PHP arrays a little sparse, so thought I’d elaborate.

The Scenario

I’m working on a Timber site (redoing this one, actually!) and had a bunch of redundant markup for a list of social links in the footer. Here’s the markup for one list item (I’m using grunt-svgstore for svg sprites – it’s fun, more here):


<!-- In footer.twig -->

<li>
    <a href="http://twitter.com/laras126" target="blank">
        <svg viewBox="0 0 100 100" class="icon icon-twitter">
            <use xlink:href="#icon-twitter"></use>
        </svg>
    </a>
</li>

That’s pretty gross to write four or five times when you are only changing the URL and part of the class names. So, in the spirit of DRY and making my life more difficult, I wanted to figure out abstracting those values into a PHP array to pass to the Twig file instead of writing everything over and over.

The Solution

In the add_to_context() function in your theme’s functions.php (and equivalent in other Twig projects), I created a simple array of strings to pass into the site-wide $context variable:


// In functions.php

function add_to_context($context) {
    
    // My array
    $social = array(
            'twitter' => 'http://twitter.com/laras126',
            'linkedin' => 'http://www.linkedin.com/in/notlaura/',
            'github' => 'http://github.com/laras126'
        );
    
    // Add social array to site context
    $context['social'] = $social;
        
    // ... probably more $context here (e.g. sidebars, menus, etc)

    // Essential (and included in Timber starter theme)
    $context['site'] = $this;
    return $context;
}

Now that content is available on any page in the site, and I’ll have that in the footer is on every page so it’s okay. If I only had this on pages for example, I would add the context within the page.php template. You want to only use global context when something really is on every view of the site.

Now, in the Twig template we have this:


<!-- In footer.twig -->

<ul class="list-social">
    {% for type, url in social %}
        <li>
            <a href="{{url}}" target="blank">
                <svg viewBox="0 0 100 100" class="icon icon-{{type}}">
                    <use xlink:href="#icon-{{type}}"></use>
                </svg>
            </a>
        </li>
    {% endfor %}
</ul>

Note that the only meaningful value in the for loop is social which must match the name of the context variable added above. The {{type}} refers to the key, and {{url}} the value of that array row.

And if you really want to go next level, you could pretty easily add that to an ACF theme options page. Okay, enjoy!


2 responses to “Iterate over Keys and Values in Twig with Timber”

  1. Hi Lara,

    Nice tutorial! Although, you forgot to add the following line above
    the function:

    add_filter(‘timber_context’, ‘add_to_context’);

    Regards,
    Fritz.

  2. Excellent! I was expecting a => to separate keys and values turns out to be a comma.