php 无法自动装配服务:参数引用类,但不存在此类服务
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/48024235/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Cannot autowire service: Argument references class but no such service exists
提问by Donal.Lynch.Msc
I'm upgrading a project from Symfony 3to Symfony 4(https://github.com/symfony/symfony/blob/master/UPGRADE-4.0.md) and I have many repository/services like this:
我正在将一个项目从Symfony 3升级到Symfony 4( https://github.com/symfony/symfony/blob/master/UPGRADE-4.0.md),我有很多这样的存储库/服务:
namespace App\Entity;
use App\Entity\Activation;
use Doctrine\ORM\EntityRepository;
use Predis\Client;
class ActivationRepository extends EntityRepository
{
// ...
}
And when I try to run the project in the browser like this:
当我尝试像这样在浏览器中运行项目时:
http://localhost:8000/login
I get this error:
我收到此错误:
(1/1) RuntimeException
Cannot autowire service "App\Entity\ActivationRepository":
argument "$class" of method
"Doctrine\ORM\EntityRepository::__construct()"
references class "Doctrine\ORM\Mapping\ClassMetadata"
but no such service exists.
Does this mean you have to create a service for "Doctrine\ORM\Mapping\ClassMetadata"in your services.yaml file?
这是否意味着您必须在 services.yaml 文件中为“Doctrine\ORM\Mapping\ClassMetadata”创建一个服务?
Thanks to autowiring my new services.yaml file is fairly small compared to the old one, which had 2000+ lines. The new services.yaml just has several of these (so far):
由于自动装配,我的新 services.yaml 文件与旧文件相比相当小,旧文件有 2000 多行。新的 services.yaml 只有其中几个(到目前为止):
App\:
resource: '../src/*'
# Controllers
App\Controller\:
resource: '../src/Controller'
autowire: true
public: true
tags: ['controller.service_arguments']
# Models
App\Model\:
resource: '../src/Model/'
autowire: true
public: true
// etc
Question: Do you really need to add service definitions to services.yaml for third party vendor classes? And if so, can I get an example of how to do that please? Any advice from anyone who has already upgraded from Symfony 3to Symfony 4would be great.
问题:您真的需要为第三方供应商类的 services.yaml 添加服务定义吗?如果是这样,我能得到一个如何做到这一点的例子吗?任何已经从Symfony 3升级到Symfony 4 的人的任何建议都会很棒。
PHP 7.2.0-2+ubuntu16.04.1+deb.sury.org+2 (cli) (built: Dec 7 2017 20:14:31) ( NTS ) Linux Mint 18, Apache2 Ubuntu.
PHP 7.2.0-2+ubuntu16.04.1+deb.sury.org+2 (cli) (build: Dec 7 2017 20:14:31) ( NTS ) Linux Mint 18, Apache2 Ubuntu。
EDIT / FYI:
编辑/仅供参考:
This is the "Doctrine\ORM\EntityRepository::__construct()" which the ActivationRepository extends:
这是 ActivationRepository 扩展的“Doctrine\ORM\EntityRepository::__construct()”:
/**
* Initializes a new <tt>EntityRepository</tt>.
*
* @param EntityManager $em The EntityManager to use.
* @param Mapping\ClassMetadata $class The class descriptor.
*/
public function __construct(EntityManagerInterface $em, Mapping\ClassMetadata $class)
{
$this->_entityName = $class->name;
$this->_em = $em;
$this->_class = $class;
}
which is located here:
位于此处:
/vendor/doctrine/orm/lib/Doctrine/ORM/EntityRepository.php
回答by Federkun
Starting from the 1.8 version of DoctrineBundle, you can extends your class using Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository
instead of Doctrine\ORM\EntityRepository
. The result will be the same, but this support the autowire.
从 1.8 版本的 DoctrineBundle 开始,您可以使用Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository
代替来扩展您的类 Doctrine\ORM\EntityRepository
。结果将是相同的,但这支持自动装配。
Example:
例子:
use App\Entity\Activation;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Common\Persistence\ManagerRegistry;
class ActivationRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Activation::class);
}
// ...
}
回答by Federkun
Do you really need to add service definitions to services.yaml for third party vendor classes?
您真的需要为第三方供应商类的 services.yaml 添加服务定义吗?
No, don't do that. My personal suggestion is: don't extend EntityRepository
. Ever. You don't want your repository's interface to have method like createQuery
or flush
. At least, you don't want that if you consider a repository just like a collection of objects. If you extend EntityRepository
you will have a leaky abstraction.
不,不要那样做。我个人的建议是:不要扩展EntityRepository
. 曾经。您不希望存储库的接口具有像createQuery
或 之类的方法flush
。至少,如果您将存储库视为对象的集合,那么您不希望这样。如果您扩展,EntityRepository
您将有一个泄漏的抽象。
Instead you can inject the EntityManager
inside your repository, and that's it:
相反,您可以注入EntityManager
存储库内部,就是这样:
use App\Entity\Activation;
use App\Repository\ActivationRepository;
use Doctrine\ORM\EntityManagerInterface;
final class DoctrineActivationRepository implements ActivationRepository
{
private $entityManager;
private $repository;
public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
$this->repository = $this->entityManager->getRepository(Activation::class);
}
public function store(Activation $activation): void
{
$this->entityManager->persist($activation);
$this->entityManager->flush();
}
public function get($id): ?Activation
{
return $this->repository->find($id);
}
// other methods, that you defined in your repository's interface.
}
No other steps are required.
不需要其他步骤。