Symfony TwigBundle 未加载任何自定义扩展

Symfony TwigBundle not loading any custom extensions

我正在努力更新 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(它们只是名为模块的捆绑包)已加载并在模板中可用。

,扩展 class 是自动连接和自动加载的, 它们可用 - 即它们列在 bin/console debug:container 特别是如果我做类似

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.                                                                                       

这清楚地表明,服务不仅正确自动装配,而且还正确标记。

如果我这样做 bin/console debug:twig none,则会列出自定义扩展(在顶部带有函数、过滤器等)。我什至尝试逐步完成 TwigBundle Compiler 过程,我很确定那里包含可调用对象。

你知道问题出在哪里吗?我该如何解决它?

免责声明:我不是很确定,依赖注入修饰是如何工作的确切地

依赖注入装饰器不会让您编写一个合适的装饰器(因为它无论如何都无法检查),但是,有一些迹象表明它不是装饰器。

主要指标:装饰 class 不依赖于装饰 class,如:它不需要作为 __construct() 的参数或以其他方式注入。

推理:装饰器应该以 cascading/chainable 的方式使用,本质上,装饰器应该像这样使用(在你的情况下不起作用!):

$instance = new Decorator2(new Decorator1(new DecoratedClass()));

和装饰器(方法)平均应该是这样的:

class Decorator {
   protected $inner;
   public function __construct(DecoratedClass $inner) {
       $this->inner = $inner;
   }
   public function someMethod($someParam) {
       // do something before, maybe change $someParam
       $returnValue = $this->inner->someMethod($someParam);
       // do something after, maybe change $returnValue  
       return $returnValue;
   }
}

symfony page on decorating actually says most of this, directly or indirectly (references this wikipedia article).

据我所知,每个 class 都必须正确添加修饰的 class(烦人的 AF)的所有函数,如:在内部对象上调用它。

现在,一种方法可能是:"well, I don't really care about actually decorating, I just want my class to be used instead of the twig environment!"

在这种情况下,您应该主动将其替换为您的 class,正如我在评论 (services.yaml) 中指出的那样:

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

应该 导致您的 class 在需要 Twig\Environmenttwig 或您的 class 时被使用具体来说。

但是,在修饰的情况下,您的 class 应该修饰它扩展的 class,而不是 class 具有的别名.

我问的真正问题是,"What is the correct way to override Twig\Environment with a child class?"

正确答案是按照与原来相同的方式定义服务。 (虽然 Symfony 默认使用 xml,所以我不得不转换)。所以这是正确的定义:

# 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'

你可以看到这是如何复制 Symfony 的:

    <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" />

并看看它与上面@Jakumi 的建议有何不同:

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

非常感谢@Cerad 和@Jakumi 协助解决问题![​​=14=]