symfonydependency-injectiontwigsymfony4twig-extension

Symfony TwigBundle not loading any custom extensions


I am working on updating Zikula from Symfony 3 to Symfony 4 (I'm working specifically in this PR at the moment). Part of this is removing Symfony's old templating mechanism and switching entirely to Twig. In the process I am running into a very unusual problem: None of the custom Twig extensions in the included Bundles or the pseudo bundles (they're just Bundles named Modules) are loaded and available in templates.

Yes, the extensions class are autowired and autoloaded and yes they are available - i.e. they are listed in bin/console debug:container and specifically if I do something like

me% bin/console debug:container AdminExtension

Information for Service "Zikula\AdminModule\Twig\Extension\AdminExtension"
==========================================================================

 ---------------- -------------------------------------------------- 
  Option           Value                                             
 ---------------- -------------------------------------------------- 
  Service ID       Zikula\AdminModule\Twig\Extension\AdminExtension  
  Class            Zikula\AdminModule\Twig\Extension\AdminExtension  
  Tags             twig.extension                                    
  Public           no                                                
  Synthetic        no                                                
  Lazy             no                                                
  Shared           yes                                               
  Abstract         no                                                
  Autowired        yes                                               
  Autoconfigured   yes                                               
 ---------------- -------------------------------------------------- 

 ! [NOTE] The "Zikula\AdminModule\Twig\Extension\AdminExtension" service or alias has been removed or inlined when the  
 !        container was compiled.                                                                                       

This clearly shows that not only is the service properly autowired, but it is also tagged correctly.

If I do bin/console debug:twig none of the custom extensions are listed (at the top with functions, filters, etc). I even tried to step through the TwigBundle Compiler process and I am quite sure the callable are being included there.

Do you have any idea what the problem is or how I might troubleshoot it?


Solution

  • The real question I was asking without realizing it was, "What is the correct way to override Twig\Environment with a child class?"

    The correct answer was to define the services in the same exact way as the original. (Symfony uses xml as a default though, so I had to convert). So this is the correct definition:

    # override TwigBundle's Twig\Environment definition with Zikula's own child class
    # see vendor/symfony/symfony/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml
    twig:
        class: Zikula\ThemeModule\Bridge\Twig\EventEnabledTwigEngine
        public: true
        arguments:
          $loader: '@twig.loader'
          $options: []
        calls:
          - [setEventDispatcher, ['@event_dispatcher']]
          - [addGlobal, ['app', '@twig.app_variable']]
          - [addRuntimeLoader, ['@twig.runtime_loader']]
        configurator: ['@twig.configurator.environment', 'configure']
    Twig_Environment: '@twig'
    Twig\Environment: '@twig'
    

    you can see how this is a copy of Symfony's:

        <service id="twig" class="Twig\Environment" public="true">
            <argument type="service" id="twig.loader" />
            <argument /> <!-- Twig options -->
            <call method="addGlobal">
                <argument>app</argument>
                <argument type="service" id="twig.app_variable" />
            </call>
            <call method="addRuntimeLoader">
                <argument type="service" id="twig.runtime_loader" />
            </call>
            <configurator service="twig.configurator.environment" method="configure" />
        </service>
        <service id="Twig_Environment" alias="twig" />
        <service id="Twig\Environment" alias="twig" />
    

    and also see how it differs from @Jakumi's suggestion above:

    Twig\Environment: Your\Class\Name
    Your\Class\Name: # NO DECORATES!!!
       arguments: ...
       calls: ...
    twig: Your\Class\Name # maybe setting it via alias is effective...
    

    Many thanks to @Cerad and @Jakumi for your assistance in solving the problem!