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

Don*_*Msc 21 php doctrine symfony symfony4

我正在将项目从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
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)

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

http://localhost:8000/login
Run Code Online (Sandbox Code Playgroud)

我收到此错误:

(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.
Run Code Online (Sandbox Code Playgroud)

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

感谢自动装配我的新服务.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
Run Code Online (Sandbox Code Playgroud)

问题:您是否真的需要为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.

编辑/ FYI:

这是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;
    }
Run Code Online (Sandbox Code Playgroud)

位于这里:

/vendor/doctrine/orm/lib/Doctrine/ORM/EntityRepository.php
Run Code Online (Sandbox Code Playgroud)

Fed*_*kun 42

从1.8版本的DoctrineBundle开始,您可以使用Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository而不是使用扩展您的类 Doctrine\ORM\EntityRepository.结果将是相同的,但这支持autowire.

例:

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

    // ...
}
Run Code Online (Sandbox Code Playgroud)


Fed*_*kun 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.
}
Run Code Online (Sandbox Code Playgroud)

不需要其他步骤。