Аргумент 1, переданный в Builder::__construct(), должен реализовывать интерфейс Knp\Menu\FactoryInterface, не указан

Используя Symfony 3.3.12, я пытаюсь использовать свой конструктор меню в качестве службы, это настраивается в AppBundle/Resources/config/services.yml и импортируется в основной config.yml как

imports:
   - { resource: "@AppBundle/Resources/config/services.yml" }

services.yml

##########################################################################
 # Menu Section   
 ##########################################################################
 AppBundle\Menu\Builder:
     arguments: 
         $factory: '@knp_menu.factory'
         $doctrine: '@doctrine'
         $token: '@security.token_storage'
     public: true
     tags:
         - { name: knp_menu.menu_builder, method: sidebarMenu, alias: sidebar }

Но я получаю эту ошибку при рендеринге как

{{ knp_menu_render('sidebar', {'template': 'Menu/knp_sidebar_menu.html.twig', 'allow_safe_labels': true, 'currentClass':'active'}) }}

Аргумент 1, переданный в Builder::__construct(), должен реализовывать интерфейс Knp\Menu\FactoryInterface, не указан, вызывается в /home/demousr/app/vendor/knplabs/knp-menu-bundle/Provider/BuilderAliasProvider.php в строке 121.

это мой строитель

namespace AppBundle\Menu;

use \Knp\Menu\FactoryInterface;
use \AppBundle\Menu\Loader\NodeLoader;
use \Doctrine\Bundle\DoctrineBundle\Registry;
use \Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;

class Builder {

    private $factory;
    private $doctrine;
    private $token;

    public function __construct(FactoryInterface $factory, Registry $doctrine, TokenStorage $token) {
        $this->factory = $factory;
        $this->doctrine = $doctrine;
        $this->token = $token->getToken();
    }

    public function sidebarMenu(array $options) {

        $menu = $this->factory->createItem('root');
        $nodeLoader = new NodeLoader($this->factory, $this->token);

        $menu->setChildrenAttribute('class', 'nav nav-sidebar');

        $em = $this->doctrine->getManager();
        $tree = $em->getRepository('AppBundle:Menu\Menu')->findOneByMenu('main');
        $roots = $em->getRepository('AppBundle:Menu\MenuItem')->getRootNodesByTree($tree);

        foreach($roots as $root){

            $item = $nodeLoader->load($root);

            if(null !== $item){
                $menu->addChild($item);
            }
        }

        return $menu;
    }

}

не могу найти где я не прав


person Jack Skeletron    schedule 16.11.2017    source источник
comment
Я не использую этот пакет, но сообщение об ошибке, похоже, указывает на то, что AliasProvider пытается создать новый ваш билдер, а не извлекать его из контейнера. Код на github, кажется, подтверждает это, хотя номер строки другой. Загляните внутрь исходного кода и посмотрите, что делает строка 121.   -  person Cerad    schedule 16.11.2017
comment
@Cerad в строке 121 BuilderAliasProvider $builder = new $class(); создает новый объект без внедрения зависимостей. Я думаю, что вместо этого следует использовать BuilderServiceProvider. Кажется, мой билдер не распознается как сервис   -  person Jack Skeletron    schedule 16.11.2017
comment
Ага. BuilderServiceProvider извлекает из контейнера.   -  person Cerad    schedule 16.11.2017
comment
@Cerad хорошо, но почему он не используется? Я добавил правильный тег в определение сервиса... документация здесь   -  person Jack Skeletron    schedule 16.11.2017
comment
@JackSkeletron, вы можете попробовать объявить свой сервис вручную (все зависимости)   -  person Adrien G    schedule 16.11.2017
comment
Может быть, кто-то, кто использует пакет, может присоединиться. Я предполагаю, что это потому, что вы используете имя класса в качестве своего идентификатора службы. У меня возникло бы искушение сказать, попробуйте установить псевдоним для имени класса и посмотреть, что произойдет, но это просто выстрел в темноту. Я бы посоветовал точно следовать примеру в документации и посмотреть, что произойдет. Я знаю, что новый автосвязывание контейнеров может в лучшем случае сбивать с толку, но старый стиль создания определений сервисов все еще будет работать.   -  person Cerad    schedule 16.11.2017
comment
@Cerad Спасибо за попытку :) У меня есть куча других сервисов, настроенных так (избиратель и т. д.), которые работают без проблем :\   -  person Jack Skeletron    schedule 16.11.2017
comment
Хорошо, я только что изменил имя класса в MenuBuilder и метод для созданияSidebarMenu, а также изменил идентификатор службы на новое имя класса, и теперь это работает. Просто большая загадка для меня.   -  person Jack Skeletron    schedule 16.11.2017
comment
Глядя на параметры конфигурации, я думаю, что каждый провайдер проверяется по очереди. И поскольку любой класс построителя в меню определяется как построитель, поставщик псевдонимов подбирает его до того, как у поставщика услуг появится шанс. Может быть интересно попробовать настроить раздел провайдеров в knp_menu. Конечно, поскольку у вас это работает, может быть лучше просто оставить его и двигаться дальше. И рассмотрите возможность публикации окончательного определения службы в качестве ответа только для дальнейшего использования.   -  person Cerad    schedule 16.11.2017


Ответы (1)


Я только что изменил имя класса в MenuBuilder и метод createSidebarMenu, а также изменил идентификатор службы на новое имя класса, и теперь это работает. Просто большая загадка для меня.

service.yml

##########################################################################
# Menu Section   
##########################################################################
AppBundle\Menu\MenuBuilder:
    arguments: 
        $factory: '@knp_menu.factory'
        $doctrine: '@doctrine'
        $token: '@security.token_storage'
    public: true
    tags:
        - { name: knp_menu.menu_builder, method: createSidebarMenu, alias: sidebar }

А это MenuBuilder.php

class MenuBuilder {

    private $factory;
    private $doctrine;
    private $token;

    public function __construct(FactoryInterface $factory, Registry $doctrine, TokenStorage $token) {
       $this->factory = $factory;
       $this->doctrine = $doctrine;
       $this->token = $token->getToken();
    }

    public function createSidebarMenu(array $options) {
        # code
    }
}
person Jack Skeletron    schedule 24.11.2017