无法自动装配服务:参数引用 class 但不存在此类服务
Cannot autowire service: Argument references class but no such service exists
我正在将项目从 Symfony 3 升级到 Symfony 4
(https://github.com/symfony/symfony/blob/master/UPGRADE-4.0.md) 我有很多这样的 repository/services:
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 薄荷 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
Do you really need to add service definitions to services.yaml for third party vendor classes?
不,不要那样做。我个人的建议是:不要延长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.
}
不需要其他步骤。
从 DoctrineBundle 的 1.8 版本开始,您可以使用 Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository
而不是 Doctrine\ORM\EntityRepository
来扩展您的 class。结果是一样的,但是这确实支持自动装配。
示例:
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);
}
// ...
}
我的问题是命名空间错误。
文件实际位置是 App\Infrastructure\MySQL\Rubric\Specification
但是命名空间设置为 App\Infrastructure\Rubric\Specification
结果“[blah blah] 但不存在此类服务”。
我正在将项目从 Symfony 3 升级到 Symfony 4 (https://github.com/symfony/symfony/blob/master/UPGRADE-4.0.md) 我有很多这样的 repository/services:
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 薄荷 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
Do you really need to add service definitions to services.yaml for third party vendor classes?
不,不要那样做。我个人的建议是:不要延长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.
}
不需要其他步骤。
从 DoctrineBundle 的 1.8 版本开始,您可以使用 Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository
而不是 Doctrine\ORM\EntityRepository
来扩展您的 class。结果是一样的,但是这确实支持自动装配。
示例:
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);
}
// ...
}
我的问题是命名空间错误。
文件实际位置是 App\Infrastructure\MySQL\Rubric\Specification
但是命名空间设置为 App\Infrastructure\Rubric\Specification
结果“[blah blah] 但不存在此类服务”。