我将项目从 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
{
// ...
}
当我尝试在浏览器中运行项目时:
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" 创建服务?
感谢自动装配我的新服务.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。
编辑/ FYI:
这是" Doctrine \ ORM \ EntityRepository :: __ construct()" ActivationRepository扩展的内容:
/**
* 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
答案 0 :(得分:36)
从DoctrineBundle的1.8版本开始,您可以使用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);
}
// ...
}
答案 1 :(得分:1)
您是否真的需要为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.
}
无需其他步骤。
答案 2 :(得分:0)
我的问题是名称空间错误。
文件实际位置为App\Infrastructure\MySQL\Rubric\Specification
但是名称空间设置为App\Infrastructure\Rubric\Specification
结果为“ [等等],但不存在这样的服务”。