【问题标题】:Symfony 3.3 injecting repositories into servicesSymfony 3.3 将存储库注入服务
【发布时间】:2017-12-05 18:41:57
【问题描述】:

我有一个捆绑包,它保存在私有 Satis 存储库中,因为它的实体和存储库在多个应用程序之间共享。

使用该捆绑包的其余应用程序是 Symfony 2.7 和 2.8 应用程序。我正在开发一个新应用程序,要求使用 Symfony 3.3。

在 symfony 3.3 应用程序中,我在 services.yml 中尝试过这个:

# Learn more about services, parameters and containers at
# http://symfony.com/doc/current/service_container.html
parameters:
    #parameter_name: value

services:
# default configuration for services in *this* file
    _defaults:
        autowire: true
        autoconfigure: true
        # this means you cannot fetch services directly from the container via $container->get()
        # if you need to do this, you can override this setting on individual services
        public: false

    # makes classes in src/AppBundle available to be used as services
    # this creates a service per class whose id is the fully-qualified class name
    CbmLtd\UvmsBundle\:
        resource: '../../vendor/cbmltd/uvms-bundle/*'
        exclude: '../../vendor/cbmltd/uvms-bundle/{Entity,Repository}'

    UvmsApiV1Bundle\:
        resource: '../../src/UvmsApiV1Bundle/*'
        exclude: '../../src/UvmsApiV1Bundle/{Entity,Repository}'

上面给出了以下例外:

无法自动装配服务“UvmsApiV1Bundle\Service\DealerService”:方法“__construct()”的参数“$repository”引用了类“CbmLtd\UvmsBundle\Repository\DealerRepository”,但不存在此类服务。它无法自动注册,因为它来自不同的根命名空间。

好的,所以我想我需要将此存储库显式声明为服务。我在 Symfony 3.3 文档中找不到任何关于将存储库声明为服务的内容,并且 2.8 语法也不起作用。

我将此添加到我的 services.yml:

services:
    ...
    CbmLtd\UvmsBundle\DealerRepository:
        class: CbmLtd\UvmsBundle\Entity\DealerRepository
        factory_service: doctrine.orm.entity_manager
        factory_method: getRepository
        arguments:
            - CbmLtd\UvmsBundle\Entity\Dealer

但我仍然得到这个异常:

无法自动装配服务“UvmsApiV1Bundle\Service\DealerService”:方法“__construct()”的参数“$repository”引用了类“CbmLtd\UvmsBundle\Repository\DealerRepository”,但不存在此类服务。它无法自动注册,因为它来自不同的根命名空间。

我无法对 CbmLtd\UvmsBundle 进行任何更改,因为它被多个应用程序使用。任何帮助,将不胜感激。我确实花了几个小时在这上面,这非常令人沮丧。

【问题讨论】:

    标签: symfony dependency-injection doctrine symfony-3.3


    【解决方案1】:

    我能够使用以下 services.yml 做到这一点:

    services:
    # default configuration for services in *this* file
        _defaults:
            autowire: true
            autoconfigure: true
    
        # this means you cannot fetch services directly from the container via $container->get()
        # if you need to do this, you can override this setting on individual services
        public: false
    
        # makes classes in src/AppBundle available to be used as services
        # this creates a service per class whose id is the fully-qualified class name
        CbmLtd\UvmsBundle\:
            resource: '../../vendor/cbmltd/uvms-bundle/*'
            exclude: '../../vendor/cbmltd/uvms-bundle/{Entity,Repository}'
    
        CbmLtd\UvmsBundle\Repository\DealerRepository:
            factory: doctrine.orm.entity_manager:getRepository
            arguments:
                - CbmLtd\UvmsBundle\Entity\Dealer
    
        UvmsApiV1Bundle\:
            resource: '../../src/UvmsApiV1Bundle/*'
            exclude: '../../src/UvmsApiV1Bundle/{Entity,Repository}'
    

    我不得不稍微改变一下我的控制器,但它现在可以工作了。

    【讨论】:

      【解决方案2】:

      尝试更改您的存储库服务声明

      your_bundle.your_entity_repository:
          class: Doctrine\ORM\EntityRepository
          factory: ['@doctrine.orm.default_entity_manager', getRepository]
          arguments:
              - YourBundle\Entity\YourEntity
      

      然后通过像这样引用它来注入 repo:

      your_bundle.your_service:
          class: YourBundle\Service\YourService
          arguments:
              - "@your_bundle.your_entity_repository"
          calls:
              - [setContainer, ['@service_container']]
      

      【讨论】:

      • 得到:“请将类添加到服务“car_base.app.partnership_repository”,即使它是由工厂构造的,因为我们可能需要添加基于编译时检查的方法调用。(3.4)
      【解决方案3】:

      您的服务声明中有错字,您忘记了“存储库”命名空间。此外,该类位于“实体”还是“存储库”中?服务 id 应该与实际的完全限定类名相同。在 services.yml 中,尝试:

      CbmLtd\UvmsBundle\Repository\DealerRepository:
          class: CbmLtd\UvmsBundle\Repository\DealerRepository
      

      代替:

      CbmLtd\UvmsBundle\DealerRepository:
          class: CbmLtd\UvmsBundle\Entity\DealerRepository
      

      【讨论】:

        【解决方案4】:

        2018+ 和 Symfony 3.3+ 答案

        您可以更进一步,使用Repositories as Services

        这样您就可以在服务配置中使用 Symfony 的自动装配和简单配置。

        1。服务

        services:
            _defaults:
                autowire: true
                autoconfigure: true
        
            CbmLtd\UvmsBundle\:
                resource: '../../vendor/cbmltd/uvms-bundle/*'
                exclude: '../../vendor/cbmltd/uvms-bundle/{Entity}'
        
            UvmsApiV1Bundle\:
                resource: '../../src/UvmsApiV1Bundle/*'
                exclude: '../../src/UvmsApiV1Bundle/{Entity}'
        

        2。存储库

        namespace CbmLtd\UvmsBundle\Repository\DealerRepository;
        
        final class DealerRepository
        {
            /**
             * @var Doctrine\ORM\EntityRepository
             */
            private $repository;
        
            public function __construct(EntityManagerInterface $entityManager)
            {
                $this->repository = $entityManager->getRepository(Dealer::class);
            }
        
            public function find($id)
            {
                return $this->repository->find($id);
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2012-08-26
          • 2018-08-15
          • 1970-01-01
          • 2015-01-03
          • 2018-08-18
          • 1970-01-01
          • 1970-01-01
          • 2018-01-23
          • 2020-06-06
          相关资源
          最近更新 更多