Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Override Twig function in Symfony

Tags:

twig

symfony

Is it possible, and how, to override a Twig function defined in a dependency?

ThirdPartyCode\HelloExtension defines hello($string name) Twig function, returning Hello, {$name}.

In my code, App\MyHelloExtension extends HelloExtension I want to override the hello($string name) function to return Bye, {$name}.

However, when I define the function with the same name, the third-party one gets used and mine is never called. If I name it differenty, e.g. hello2 it works fine.

like image 996
Ivo Valchev Avatar asked Dec 09 '25 16:12

Ivo Valchev


1 Answers

You can either completely replace the existing function by making sure it will not be loaded. You can do this by writing a CompilerPass that works in the final step of building the Service Container. This CompilerPass would look for the service by its id/class name, whether it is registered and then removes it from the container. This would fully remove the existing Extension and you can load your extension in its place.

See: https://symfony.com/doc/current/service_container/compiler_passes.html

Alternatively you might want to use the logic from the existing extension and just build on top of it. For this service decoration might be a good fit, as decorated services replace the original ones while still being able to access the underlying decorated service if necessary.

services:
    App\MyHelloExtension:
        decorates: ThirdpartyCode\Extension
        arguments:
            - '@App\MyHelloExtension.inner' # this passes the decorated service, i.e. the original extension as an argument, see code snippet below

This would make sure that whenever something retrieves the service ThirdpartyCode\Extension from the container they will get your extension. Meaning your extension is loaded in its place instead. This works particularly well when your code either extends the existing extension (as seen in your code snippets) or uses composition like this:


class MyHelloExtension extends TwigExtension
{
    private $originalExtension;

    public function __construct(HelloExtension $helloExtension)
    {
        $this->originalExtension = $helloExtension;
    }

    // ...

    public function hello($name)
    {
        // Your method can still utilize the underlying original method if necessary.
        return $this->originalExtension->hello() . ' ' . $name;
    }
}

See: https://symfony.com/doc/current/service_container/service_decoration.html

When you decorate the service you have to be careful that only one of the extensions is registered in Twig. You should probably make sure autoconfigure: false is set on your own extension and that you don't tag it as twig.extension.

like image 77
dbrumann Avatar answered Dec 11 '25 22:12

dbrumann



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!