6 min read

Views and Twig in Symfony: Everything You Need to Know

Learn the basics of working with Views and Twig in Symfony, the PHP framework that simplifies web development. Discover how to show a view, use optional parameters in the render method, create global variables, and more. By using Twig, you can make your views more dynamic and reusable. Join Code With Dary as he guides you through everything you need to know about Views and Twig in Symfony.

Welcome to our tutorial on Views and Twig in Symfony, the PHP framework that simplifies web development. In this tutorial, we will dive into the basics of working with views and Twig in Symfony.

If you have a basic understanding of controllers, the next logical step is to focus on views. A view represents the template that will be shown to the end-user on the screen. Views in Symfony go deeper than basic .html files, as we will use a custom templating engine called Twig. Compared to views in PHP, Twig has its syntax and learning curve.

Showing a View

To show a view from a controller, you need to return the render() method. By default, index() methods inside controllers return JSON, and it is finally time to get rid of it.

If you are using a modern code editor, you will see that the render() method throws an error. This happens because it is required to add the path of a Twig template.

By default, Twig templates are stored inside the /templates directory in the root of a directory where you can find a base file called base.html.twig. For this example, we will create a new file called /templates/index.html.twig, where we will define a simple header.

<h1>
    Welcome to my Symfony course :)
</h1>

Keep in mind that you do not need to define the /templates directory inside the render() method, because the render() method knows that it needs to look inside the templates directory.

#[Route('/movies', name: 'movies')]
public function index(): Response
{
    return $this->render('index.html.twig');
}

Once you refresh your 127.0.0.1:8000/movies endpoint, you will see the h1 printed out.

Optional Parameters in the Render Method

The render() method accepts an optional second parameter. Later on, we’ll learn how to interact with the database inside the controller. You need to send some kind of data back to the view. To do this, we can add a comma after our first parameter (which is the view name), then we’re going to return an array straight into the view.

#[Route('/movies', name: 'movies')]
public function index(): Response
{
    return $this->render('index.html.twig', [
        'title' => 'Inception'
    ]);
}

It is a bit different to print out values inside Twig since it needs to be wrapped around a double set of curly braces {{ }}. Then inside the curly braces, we can simply write down the key name from the controller. We do not need to add a $ sign to let our file know that we’re working with a variable, Twig will automatically identify it as a variable.

<h1>
    {{ title }}
</h1>

More Information about Variables

A pretty cool feature in Symfony is the dump() method, which is a function that will provide more information about a template variable.

<h1>
    {{ dump(title) }}
</h1>

Once you refresh the 127.0.0.1:8000/movies endpoint, you can see that the data type of our title is a string.

Twig Layout Explained

When developing large-scale web applications, you usually want to reuse components, especially when it comes to layouts. You don’t want to redefine your stylesheet, JavaScript file, font awesome icons, and all those other utilities on every single page.

Even if we dive into the actual content of a page, you don’t want to define your head tags and/or footer tags for every single page.

What you should be doing instead is using the base.html.twig file as your layout, and add content that changes inside the index.html.twig file.

Let’s redefine our base.html.twig file and see what we got here.

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>{% block title %}Welcome!{% endblock %}</title>
        {# Run `composer require symfony/webpack-encore-bundle`
           and uncomment the following Encore helpers to start using Symfony UX #}
        {% block stylesheets %}
            {#{{ encore_entry_link_tags('app') }}#}
        {% endblock %}

        {% block javascripts %}
            {#{{ encore_entry_script_tags('app') }}#}
        {% endblock %}
    </head>
    <body>
        {% block body %}{% endblock %}
    </body>
</html>

Right here, you can see some elements that we haven’t seen before.

CodeExplanation
{% block {NAME} %} {% endblock &}A block is a place or location where a child template can extend its content. If we extend the base file inside the index file, you don’t need to define the title tags but just the blocks in case you want to change the value
{% block body %} {% endblock %}Main content of the index page will be replaced with the block body inside the body tags, this is the location where all the magic will happen

Let’s navigate to the index.html.twig file and remove everything we got. If you want to overwrite the base.html.twig file, you got to make sure that you extend that page on the first line.

What we are doing right below our extends, is saying that we want to copy the entire base.html.twig page behind the scenes, and edit certain blocks.

An example might be the following, where we extend the body block.

{% block body %}
    <h1>
        New body extended from the base.html.twig file
    </h1>
{% endblock %}

Loops inside Twig

Before we can loop over values

inside our Twig, we need to create an array inside the controller that we pass to the view.

#[Route('/movie', name: 'movies')]
public function index(): Response
{
    $movies = [ 'Avengers: Endgame', 'Inception' , 'Loki', 'Black Widow'];

    return $this->render('index.html.twig', array(
        'movies' => $movies
    ));
}

Adding {{ movies }} inside the view won’t work because you can’t print out an array as a string, so we got to make sure that we loop over our array values.

{% block body %}
    {% for movie in movies %}
        <li>
            {{ movie }}
        </li>
    {% endfor %}
{% endblock %}

If we refresh our /movies endpoint, you will see that all movies have been printed out as a list item.

Global Variables

When working on projects, you sometimes want to define a variable that you can use throughout your entire application. Instead of passing it through every controller, you can define a global variable inside the /config/packages/twig.yaml file.

Inside the twig.yaml file, we need to create a new section below the default_path, where we need to pass in a name and value.

twig:
    default_path: '%kernel.project_dir%/templates'
    globals:
        project_title: Code With Dary

Printing the value of project_title out in the view works in the same way as printing out any variable.

{% block body %}
    {{ project_title }}
{% endblock %}

Conclusion

In this tutorial, we have covered the basics of working with Views and Twig in Symfony. We have learned how to show a view, use optional parameters in the render method, create global variables, and more. By using Twig, we can make our views more dynamic and reusable.

We hope that this tutorial has been helpful to you, and if you have any questions or feedback, please don’t hesitate to contact us. Thank you for reading, and happy coding!