Symfony TwigBundle не загружает никаких пользовательских расширений

Я работаю над обновлением Zikula с Symfony 3 до Symfony 4 (я работаю конкретно в этот PR на данный момент). Частично это связано с удалением старого механизма шаблонов в Symfony и полным переходом на Twig. В процессе я столкнулся с очень необычной проблемой: ни одно из настраиваемых расширений Twig в включенные пакеты или псевдо-пакеты (это просто пакеты с именем Modules) загружаются и доступны в шаблонах.

Да, класс расширений автоматически подключается и загружается, и да они доступны, т. е. перечислены в 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 ни одно из пользовательских расширений не будет указано (вверху с функциями, фильтрами и т. Д.). Я даже попытался пройти через , и я совершенно уверен, что вызываемые объекты включены туда.

Вы хоть представляете, в чем проблема или как я могу ее устранить?


person craigh    schedule 11.12.2019    source источник
comment
Я забыл упомянуть, что вы можете увидеть результаты проблемы, когда сделаете lint:twig, как это сделано здесь: travis-ci.org/zikula/core/jobs/623444067#L860   -  person craigh    schedule 11.12.2019
comment
Автоматическое подключение сервисов в пакетах является необычным. Обычно вы определяете их вручную в AdminModule / Resources / config / services.yaml. У меня нет недавнего тестового примера с удобными связками, но, возможно, стоит попробовать.   -  person Cerad    schedule 11.12.2019
comment
@Cerad - спасибо, что нашли время ответить. Я прочитал так много ваших ответов здесь и испытываю огромное уважение.   -  person craigh    schedule 11.12.2019
comment
@Cerad Я снова попытаюсь вручную подключить сервисы и дам вам знать.   -  person craigh    schedule 11.12.2019
comment
хорошо - я обнаружил, что точка отказа заключается в том, что мы украшаем Twig/Environment класс / службу (здесь: github.com/zikula/core/blob/). Итак, если я исключу определение услуги украшения, тогда все расширения будут добавлены, как и ожидалось. Так что, видимо, мы неправильно оформляем. Как правильно украсить?   -  person craigh    schedule 12.12.2019
comment
Похоже, они пытаются добавить диспетчер событий в службу twig. Никогда ничего подобного не пробовал. Удачи.   -  person Cerad    schedule 12.12.2019
comment
они == меня. да, это идея. это хорошо работало в symfony 3.   -  person craigh    schedule 12.12.2019
comment
Ваш двигатель всегда заменяет ветку? если да, не используйте decorate, а сделайте Twig\Environment: [yourclass] и [yourclass]: ... alias: twig, что, надеюсь, сработает. Я твердо верю, что decorates подразумевает семантику, которую ваш класс не выполняет (в частности: он не реализует шаблон декоратора). Внимательно прочтите: symfony.com/doc/current/service_container/   -  person Jakumi    schedule 12.12.2019


Ответы (2)


Отказ от ответственности: я не совсем уверен, как работает оформление внедрения зависимостей точно.

Декорация внедрения зависимостей не заставляет вас писать правильный декоратор (поскольку его все равно нельзя проверить), однако есть некоторые признаки того, что это не декоратор.

Основной индикатор: класс украшения не зависит от класса декорирования, например: он не требуется в качестве параметра для __construct() или вводится в противном случае.

Обоснование: декораторы должны использоваться каскадно / цепочкой, по сути, декораторы должны использоваться следующим образом (в вашем случае не работает!):

$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 по декорированию фактически прямо или косвенно говорится о большей части этого (ссылки эту статью в Википедии).

Насколько я могу судить, каждый класс должен был бы правильно добавить все функции декорированного класса (раздражающий AF), например: вызвать его на внутреннем объекте.

Итак, один из подходов может заключаться в следующем: «Ну, я действительно не забочусь о собственном декорировании, я просто хочу, чтобы мой класс использовался вместо среды веточки!»

В этом случае вам следует активно заменить его своим классом, как я указал в своем комментарии (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...

Что должно привести к тому, что ваш класс будет использоваться всякий раз, когда что-то требует Twig\Environment или twig или конкретно вашего класса.

Однако в случаях украшения ваш класс должен украшать класс, который он расширяет, а не псевдоним этого класса.

person Jakumi    schedule 12.12.2019
comment
Спасибо, Джакуми. Как я сказал @Cerad выше, я читал многие ваши сообщения в прошлом и испытываю огромное уважение. С учетом сказанного, я пытаюсь поработать над этим и вернусь к вам. Мои первые попытки не увенчались успехом. Я вернусь. Благодарность! - person craigh; 12.12.2019
comment
Я установил конфигурацию так, как вы предлагаете (см. Здесь: github.com/zikula/core/pull/3991/commit/), но он еще не работает: использование debug:container twig приводит к Fatal error: Uncaught ...\ServiceNotFoundException: The service "Zikula\RoutesModule\Helper\ViewHelper" has a dependency on a non-existent service "twig.loader". Таким образом, это означает, что служба twig.loader больше не создается или не имеет псевдонима правильно. Что очень странно. Надеюсь, у вас есть дополнительная информация. заранее спасибо! - person craigh; 13.12.2019
comment
@craigh ошибка в совершенно другом модуле. но ошибка все еще странная. Я предполагаю, что раньше ошибки не было ...? - person Jakumi; 13.12.2019
comment
очевидно, twig.loader только добавляется, если существует twig идентификатор службы, я просто предполагаю на этом этапе. попытка добавить alias: twig в вашу службу может иметь значение ... или, возможно, просто полностью отбросить строку ...; o / - person Jakumi; 13.12.2019
comment
прямо сейчас мне интересно, лучше ли было бы настроить ваш класс через проход компилятора, и, возможно, компилятор, например github.com/symfony/twig-bundle/blob/, который вместо этого просто устанавливает ваш класс через setClass на $definition, как здесь: symfony.com/doc/current/service_container/ ... - person Jakumi; 13.12.2019
comment
То же самое я задавал вопросом о передаче компилятора. Я попробую завтра и вернусь к вам. - person craigh; 13.12.2019

Настоящий вопрос, который я задавал, не осознавая этого, был: «Как правильно переопределить Twig\Environment с помощью дочернего класса?»

Правильный ответ заключался в том, чтобы определить услуги точно так же, как в оригинале. (Тем не менее, 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'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" />

а также посмотрите, чем он отличается от предложения @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 за помощь в решении проблемы!

person craigh    schedule 13.12.2019