Symfony 4.1 twig extension
Asked Answered
P

1

1

In Symfony 4.1 I created an twig extension and I tried to use it as an service

twig.extension.active.algos:
    class: App\Twig\AppExtension
    public: true
    tags:
        - { name: twig.extension, priority: 1024 }

Unfortunately I receive 'Unable to register extension "App\Twig\AppExtension" as it is already registered' After many searches I saw that there was a bag in the version of symfony 3.4 but they say the error would have solved. So it's my mistake or just another mistake from symfony team.

My extension is:

use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;

class AppExtension extends \Twig_Extension {

public function getFunctions() {
    return array(
        new \Twig_SimpleFunction('get_active_algos', array($this, getActiveAlgos')),
    );
}

public function getActiveAlgos()
{
    return [1,2,3];
}

public function getName()
{
    return 'get_active_algos';
}
}
Pellitory answered 18/7, 2018 at 15:12 Comment(3)
You should be extending AbstractExtension per the example. And unless you disabled autowire/autoconfig then there is no longer a need for any entry in the services.yaml file.Meperidine
First of all, in the official example was created an Twig Extension for a filter. but I need a Twig Extension for a function. I need to define that extension as a service because I need to inject DoctrineEntityManagerPellitory
Defining filters and functions are almost identical. You can check the twig docs if you can't figure it out. The code you posted comes from Twig 1.x. 2.x has some changes. In particular, 2x uses namespaces.Meperidine
M
4

Got bored. Here is a working example of a custom twig function for S4.1. No service configuration required (Update: except for the added $answer argument). I even injected the default entity manager using autowire just because.

namespace App\Twig;

use Doctrine\ORM\EntityManagerInterface;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;

class TwigExtension extends AbstractExtension
{
    private $em;
    private $answer;

    public function __construct(EntityManagerInterface $em, int $answer)
    {
        $this->em = $em;
        $this->answer = $answer;
    }
    public function getFunctions()
    {
        return array(
            new TwigFunction('get_active_algos', [$this, 'getActiveAlgos']),
        );
    }
    public function getActiveAlgos()
    {
        $dbName = $this->em->getConnection()->getDatabase();
        return 'Some Active Algos ' . $dbName . ' ' . $answer;
    }
}

Update: Based on the first comment, I updated the example to show injecting a scaler parameter which autowire cannot handle.

# services.yaml
App\Twig\TwigExtension:
    $answer: 42

Note that there is still no need to tag the service as an extension. Autoconfig takes care of that by automatically tagging all classes which extend the AbstractExtension.

Meperidine answered 19/7, 2018 at 14:50 Comment(2)
I did not know that an interface/class could be used without it being injected. However, I still need to define that twig as a service because I have to inject another service that has a parameters.Pellitory
Strictly speaking it is already a service. "bin/console debug:container" will show it. You just did not have to explicitly configure it thanks to the recently introduced autowire/autoconfig capability. So you can of course define it the "old fashion" way but it is worthwhile to understand the new stuff.Meperidine

© 2022 - 2024 — McMap. All rights reserved.