问题
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