无法自动装配服务:参数引用类,但不存在此类服务

问题描述 投票:0回答:5

我正在将项目从 Symfony 3 升级到 Symfony 4https://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
{
    // ...
}

当我尝试在浏览器中运行项目时,如下所示:

http://localhost:8000/login

我收到此错误:

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

这是否意味着您必须在 services.yaml 文件中为 “Doctrine\ORM\Mapping\ClassMetadata” 创建服务?

由于自动装配,我的新 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

问题: 您真的需要将服务定义添加到第三方供应商类的 services.yaml 中吗?如果是这样,我可以举个例子来说明如何做到这一点吗? 任何已经从 Symfony 3 升级到 Symfony 4 的人的任何建议都会很棒。

PHP 7.2.0-2+ubuntu16.04.1+deb.sury.org+2 (cli)(构建时间:2017 年 12 月 7 日 20:14:31)( NTS ) Linux Mint 18、Apache2 Ubuntu。

编辑/仅供参考:

这是 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;
    }

位于此处:

/vendor/doctrine/orm/lib/Doctrine/ORM/EntityRepository.php
php symfony doctrine symfony4
5个回答
75
投票

从 DoctrineBundle 1.8 版本开始,您可以使用

Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository
而不是
Doctrine\ORM\EntityRepository
来扩展您的类。结果是一样的,但这确实支持自动装配。

示例:

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

    // ...
}

5
投票

您真的需要将服务定义添加到第三方供应商类的 services.yaml 中吗?

不,不要这样做。我个人的建议是:不要延长

EntityRepository
。曾经。您不希望存储库的界面具有像
createQuery
flush
这样的方法。至少,如果您将存储库视为对象集合,那么您不希望出现这种情况。如果你扩展
EntityRepository
你将会有一个有漏洞的抽象。

相反,您可以将

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

无需其他步骤。


3
投票

我的问题是命名空间错误。 文件真实位置是

App\Infrastructure\MySQL\Rubric\Specification
但命名空间设置为
App\Infrastructure\Rubric\Specification

结果“[等等]但不存在这样的服务”。


3
投票

我遇到了这个问题。我的服务有一个私有构造函数。我必须改变:

private function __construct(

public function __construct(

0
投票

我遇到了同样的问题,但使用了另一种解决方案,在 autowire yaml 配置文件中添加工厂方法。

存储库.yml:

    MyCompany\SurveyBundle\Repository\SurveyQuestionRepository:
       class: MyCompany\SurveyBundle\Repository\SurveyQuestionRepository
       factory:    ["@doctrine.orm.entity_manager", getRepository]
       arguments:
           - MyCompany\SurveyBundle\Entity\SurveyQuestion

SurveyQuestionRepository 只是扩展了 EntityRepository

© www.soinside.com 2019 - 2024. All rights reserved.