Symfony: How to call a PHP function from Twig template

Updated: January 13, 2024 By: Guest Contributor Post a comment

Introduction

Symfony’s Twig templates offer a robust system for maintaining a clear separation of concerns, clearly distinguishing the logic layer from the presentation layer. However, at times it becomes necessary to invoke a PHP function directly within a Twig template. This tutorial will guide you through the process of exposing PHP functions to Twig, ranging from basic usage to more advanced scenarios.

Before we proceed, it’s critical to understand that calling PHP functions from Twig templates should be avoided whenever possible in favor of using native Twig extensions or filters. This maintains the cleanliness and maintainability of your application. Symfony provokes a clean design pattern called ‘Twig Extensions’, which allow you to extend Twig and create custom filters and functions.

Creating a Basic Twig Extension

The simplest way to call a PHP function from a Twig template is to create a Twig extension that encapsulates the function. Here’s how to create a basic Twig extension in Symfony:

// src/Twig/AppExtension.php
namespace App\Twig;

use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;

class AppExtension extends AbstractExtension
{
    public function getFunctions()
    {
        return [
            new TwigFunction('my_function', [this, 'myFunction']),
        ];
    }

    public function myFunction($value)
    {
        // Your PHP function code here
        return 'Processed: '.$value;
    }
}

After creating your Twig extension, register it as a service in config/services.yaml:

services:
    App\Twig\AppExtension:
        tags:
            - { name: 'twig.extension' }

To use your new function within a Twig template, simply call it like you would any other Twig function:

{{ my_function('input') }}

The action will result in Processed: input being displayed in the template.

Exposing Built-In PHP Functions

Sometimes you may want to expose built-in PHP functions directly. Symfony allows you to register global PHP functions that can be called from any Twig template. To add a global Twig function, specify it in the twig configuration using globals:

# config/packages/twig.yaml
twig:
    globals:
        my_strtolower: '@=function("strtolower")'

In your Twig template, the function can then be used like any other global variable or function:

{{ my_strtolower('UPPERCASE') }}

This would output ‘uppercase’ in your template.

Using PHP Functions as Filters

You can also expose PHP functions as Twig filters. For instance, if you wanted to provide the strip_tags PHP function as a Twig filter, here’s how you can define it inside a Twig extension:

// src/Twig/AppExtension.php
 // ... existing code ...

class AppExtension extends AbstractExtension
{
    // ... existing code ...

    public function getFilters()
    {
        return [
            new TwigFilter('strip_tags', 'strip_tags'),
        ];
    }
}

To apply this filter to a variable in a template you would do the following:

{{ 'Some <strong>content</strong>'|strip_tags }}

The output will be Some content, with the HTML tags stripped away.

Advanced Use Cases

In a more advanced scenario, you might have a PHP function that requires access to the service container. For this purpose, you will need to inject the necessary services into your Twig extension:

// src/Twig/AppExtension.php
// ... existing code ...

use Psr\Container\ContainerInterface;

class AppExtension extends AbstractExtension
{
    private $container;
    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;
    }

    public function getFunctions()
    {
        return [
            new TwigFunction('service_function', [this, 'serviceFunction']),
        ];
    }

    public function serviceFunction(...$args)
    {
        $service = $this->container->get('my_service');
        return $service->doSomething(...$args);
    }
}

We also need to tweak the service declaration to inject the container into our extension:

# config/services.yaml
services:
    App\Twig\AppExtension:
        arguments: ['@service_container']
        tags:
            - { name: 'twig.extension' }

Now within your Twig template, you can call this new function as such:

{{ service_function('param') }}

This would result in output determined by the 'my_service' service’s doSomething method.

Conclusion

Despite being a powerful tool, calling PHP functions from Twig templates in Symfony is most appropriate when such functions enhance the template without breaching its responsibilities. Custom Twig extensions, filters, and global functions not only streamline templates but maintain the core design principles of clean code architecture.