Symfony 3.3 injecting repositories into services

我与影子孤独终老i 提交于 2019-12-22 08:01:25

问题


I have a bundle which is held in a private Satis repository as its entities and repositories are shared between multiple application.

The rest of the applications that consume that bundle are Symfony 2.7 and 2.8 applications. I'm working on a new application and the requirement is to use Symfony 3.3.

In the symfony 3.3 application I have tried this in my 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}'

The above gives the following exception:

Cannot autowire service "UvmsApiV1Bundle\Service\DealerService": argument "$repository" of method "__construct()" references class "CbmLtd\UvmsBundle\Repository\DealerRepository" but no such service exists. It cannot be auto-registered because it is from a different root namespace.

Ok, so I guess I need to explicitly declare this repository as a service. I cannot find anything in Symfony 3.3 documentation about declaring a repository as a service, and the 2.8 syntax doesn't work either.

I added this to my 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

But I still get this exception:

Cannot autowire service "UvmsApiV1Bundle\Service\DealerService": argument "$repository" of method "__construct()" references class "CbmLtd\UvmsBundle\Repository\DealerRepository" but no such service exists. It cannot be auto-registered because it is from a different root namespace.

I cannot make any changes to CbmLtd\UvmsBundle as this is used by multiple applications. Any help would be appreciated. I've literally spent hours on this, it's very frustrating.


回答1:


I was able to do this using the following 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}'

I had to change my controller slightly but it's working now.




回答2:


2018+ and Symfony 3.3+ answer

You can take this even further and use Repositories as Services.

That way you'll make use of Symfony's autowiring and easy configuration in services config.

1. Services

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. Repository

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);
    }
}



回答3:


try to change your repository service declaration

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

and then inject the repo by referencing it like this:

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



回答4:


You have a typo in your service declaration, you forgot the "repository" namespace. Also, is the class located in "Entity" or in "Repository"? The service id should be the same as the actual fully-qualified class name. In services.yml, Try:

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

Instead of:

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


来源:https://stackoverflow.com/questions/44869590/symfony-3-3-injecting-repositories-into-services

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!