Skip to content

Rendering emails with Twig in Symfony2

by rich on December 16th, 2011

I’ve been experimenting with sending emails but rendering the content with Twig. This allows emails to extend a standard layout where required, but also gives us the flexibility to insert other content into the template which may be required. In the first instance, we’re interested in supplying the email subject here.

The concept is simple – within Symfony2, firstly get Twig from the container or inject it accordingly. You can then render the template as a whole, and also extract any other items required. My example is taken from a listener class I’ve been using, but the concepts can be applied appropriately depending on where you want to use it:

class MyListener
{
    protected $mailer;
    protected $twig;
 
    public function __construct(\Swift_Mailer $mailer, \Twig_Environment $twig)
    {
        $this->mailer = $mailer;
        $this->twig = $twig;
    }
 
    public function onMyevent($myEvent)
    {
        $emailTo = $myEvent->getEmailTo();
 
        // Load the template in
        $templateFile = "MyBundle:emails:myEmailTemplate.twig";
        $templateContent = $this->twig->loadTemplate($templateFile);
 
        // Render the whole template including any layouts etc
        $body = $templateContent->render(array("someParam" => "foo"));
 
        // Get the subject block out
        // If the block doesn't exist, use a default
        $subject = ($templateContent->hasBlock("subject")
            ? $templateContent->renderBlock("subject", array("param1" => $someInformation->foo))
            : "Default subject here");
 
        $subject = trim($subject);
 
        // Send email
        $message = \Swift_Message::newInstance()
            ->setSubject($subject)
            ->setFrom("info@example.com")
            ->setTo($emailTo)
            ->setBody($body)
        ;
        $this->mailer->send($message);
    }
}

This means we can put something like the following in our template file:

{% extends "MyBundle:emails:emailLayout.twig" %}
 
{# This block is rendered in emailLayout.twig #}
{% block body %}
Hello, world. This is your email content here
{% endblock %}
 
{% block subject %}
Your subject line goes here
{% endblock %}

I was hoping to use the Twig {% spaceless %} tag, but it appears that it’s only available for HTML (sadly this PR has been closed; shame as it would have been useful). Hence the trim() call when retrieving the subject.

Of course, you can extend the above to inject in default email-FROM-addresses and names, template names and so on where appropriate.

Update: Thanks to Fabien for pointing out (comments below) that you can remove whitespace by using the following (hyphens at the end of the opening block tag and at the start of endblock:

{% block subject -%}
Your subject line goes here
{%- endblock %}

From → php, symfony, web

2 Comments
  1. Fabien permalink

    spaceless is only useful to remove spaces between HTML tags. What you want here is to remove the spaces between Twig tags. This is easy to do:

    {% block subject -%}
    Your subject line goes here
    {%- endblock %}

    More information here: http://twig.sensiolabs.org/doc/templates.html#whitespace-control

    • rich permalink

      ah, perfect – I saw the {{- value -}} example, but couldn’t see how it related to a static text string in the template. Putting it on the block tags makes perfect sense. Thanks for clarifying! :-)

Leave a Reply

Note: XHTML is allowed. Your email address will never be published.

Subscribe to this comment feed via RSS