542

Anyone knows how to concatenate strings in twig? I want to do something like:

{{ concat('http://', app.request.host) }}
dreftymac
  • 31,404
  • 26
  • 119
  • 182
stoefln
  • 14,498
  • 18
  • 79
  • 138

11 Answers11

1036

This should work fine:

{{ 'http://' ~ app.request.host }}

To add a filter - like 'trans' - in the same tag use

{{ ('http://' ~ app.request.host) | trans }}

As Adam Elsodaney points out, you can also use string interpolation, this does require double quoted strings:

{{ "http://#{app.request.host}" }}
bobbel
  • 3,327
  • 2
  • 26
  • 43
Alessandro Desantis
  • 14,098
  • 1
  • 26
  • 32
  • 4
    Thanks for you answer. But it appears that | trans filter doesn't work on that (eg: {{ 'test_' ~ name | trans }} won't translate my items. Do you have an idea how to do that? thx! – guillaumepotier Jan 08 '12 at 14:21
  • 14
    Yes, you have to create a variable to hold the concatenated string. E.g.: ```{% set foo = 'http://' ~ app.request.host %}```. And then you can do: ```{{ foo | trans }}```. – Alessandro Desantis Jan 08 '12 at 17:58
  • 78
    Translation in one line: {{ ('test_' ~ name) | trans }} – Johnny Mar 04 '12 at 10:11
  • 7
    Thank you. So the problem is that filters have higher precedence than the concatenation operator. – Alessandro Desantis Mar 04 '12 at 14:31
  • This worked for me to concat strings passed into a function as one argument, with filters on the variable and the function token itself: `{{ form_open('admin/files/?path='~file_path|urlencode)|raw }}` No need for an extra variable. – Wesley Murch Mar 09 '12 at 06:28
  • Thanks for your post!! It did save me much time solving this issue. – Calios Jun 18 '14 at 07:20
  • Thank you! Wrapping the concatenation in parenthesis helped with trans. – trickyzter Apr 26 '17 at 07:33
  • Please note, that the hash-sign must be before the open curly brace to make it interpolate. Also it must be double quotes. – Markus Zeller Aug 08 '17 at 11:00
114

Also a little known feature in Twig is string interpolation:

{{ "http://#{app.request.host}" }}
Adam Elsodaney
  • 7,722
  • 6
  • 39
  • 65
33

The operator you are looking for is Tilde (~), like Alessandro said, and here it is in the documentation:

~: Converts all operands into strings and concatenates them. {{ "Hello " ~ name ~ "!" }} would return (assuming name is 'John') Hello John!. – http://twig.symfony.com/doc/templates.html#other-operators

And here is an example somewhere else in the docs:

{% set greeting = 'Hello' %}
{% set name = 'Fabien' %}

{{ greeting ~ name|lower }}   {# Hello fabien #}

{# use parenthesis to change precedence #}
{{ (greeting ~ name)|lower }} {# hello fabien #}
Elikill58
  • 4,050
  • 24
  • 23
  • 45
Nabil Kadimi
  • 10,078
  • 2
  • 51
  • 58
22

In this case, where you want to output plain text and a variable, you could do it like this:

http://{{ app.request.host }}

If you want to concatenate some variables, alessandro1997's solution would be much better.

alghimo
  • 2,899
  • 18
  • 11
  • 2
    this does not work for me, cause i have to url_encode the whole string with another filter... – stoefln Oct 10 '11 at 08:03
16
{{ ['foo', 'bar'|capitalize]|join }}

As you can see this works with filters and functions without needing to use set on a seperate line.

Simon Epskamp
  • 8,813
  • 3
  • 53
  • 58
12

Whenever you need to use a filter with a concatenated string (or a basic math operation) you should wrap it with ()'s. Eg.:

{{ ('http://' ~ app.request.host) | url_encode }}

lsouza
  • 2,448
  • 4
  • 26
  • 39
9

You can use ~ like {{ foo ~ 'inline string' ~ bar.fieldName }}

But you can also create your own concat function to use it like in your question:
{{ concat('http://', app.request.host) }}:

In src/AppBundle/Twig/AppExtension.php

<?php

namespace AppBundle\Twig;

class AppExtension extends \Twig_Extension
{
    /**
     * {@inheritdoc}
     */
    public function getFunctions()
    {
        return [
            new \Twig_SimpleFunction('concat', [$this, 'concat'], ['is_safe' => ['html']]),
        ];
    }

    public function concat()
    {
        return implode('', func_get_args())
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'app_extension';
    }
}

In app/config/services.yml:

services:
    app.twig_extension:
        class: AppBundle\Twig\AppExtension
        public: false
        tags:
            - { name: twig.extension }
luchaninov
  • 6,792
  • 6
  • 60
  • 75
6

In Symfony you can use this for protocol and host:

{{ app.request.schemeAndHttpHost }}

Though @alessandro1997 gave a perfect answer about concatenation.

Minras
  • 4,136
  • 4
  • 18
  • 18
5

Quick Answer (TL;DR)

  • Twig string concatenation may also be done with the format() filter

Detailed Answer

Context

  • Twig 2.x
  • String building and concatenation

Problem

  • Scenario: DeveloperGailSim wishes to do string concatenation in Twig
    • Other answers in this thread already address the concat operator
    • This answer focuses on the format filter which is more expressive

Solution

  • Alternative approach is to use the format filter
  • The format filter works like the sprintf function in other programming languages
  • The format filter may be less cumbersome than the ~ operator for more complex strings

Example00

  • example00 string concat bare

    
      {{ "%s%s%s!"|format('alpha','bravo','charlie') }}
    
      --- result --
    
      alphabravocharlie!
    
      

Example01

  • example01 string concat with intervening text

    
      {{ "The %s in %s falls mainly on the %s!"|format('alpha','bravo','charlie') }}
    
      --- result --
    
      The alpha in bravo falls mainly on the charlie!
    
      

Example02

  • example02 string concat with numeric formatting

  • follows the same syntax as sprintf in other languages

    
      {{ "The %04d in %04d falls mainly on the %s!"|format(2,3,'tree') }}
    
      --- result --
    
      The 0002 in 0003 falls mainly on the tree!
    
      

See also

Elikill58
  • 4,050
  • 24
  • 23
  • 45
dreftymac
  • 31,404
  • 26
  • 119
  • 182
3

To mix strings, variables and translations I simply do the following:

    {% set add_link = '
    <a class="btn btn-xs btn-icon-only" 
       title="' ~ 'string.to_be_translated'|trans ~ '" 
       href="' ~ path('acme_myBundle_link',{'link':link.id})  ~ '">
    </a>
    ' %}

Despite everything being mixed up, it works like a charm.

Gingi
  • 145
  • 8
-2

The "{{ ... }}"-delimiter can also be used within strings:

"http://{{ app.request.host }}"
user2345998
  • 649
  • 13
  • 31