Не удается autowire service: аргумент ссылается на класс, но такой службы не существует
Я обновляю проект с Symfony 3 to Symfony 4 (https://github.com/symfony/symfony/blob/master/UPGRADE-4.0.md) и у меня есть много репозиториев / сервисов, подобных этому:
namespace AppEntity;
use AppEntityActivation;
use DoctrineORMEntityRepository;
use PredisClient;
class ActivationRepository extends EntityRepository
{
// ...
}
и когда я пытаюсь запустить проект в браузере такой:
http://localhost:8000/login
Я получаю эту ошибку:
(1/1) RuntimeException
Cannot autowire service "AppEntityActivationRepository":
argument "$class" of method
"DoctrineORMEntityRepository::__construct()"
references class "DoctrineORMMappingClassMetadata"
but no such service exists.
означает ли это, что вы должны создать службу для "DoctrineORMMappingClassMetadata" в вашей сервисы.файл yaml?
благодаря autowiring мои новые услуги.файл yaml довольно мал по сравнению со старым, в котором было 2000+ строк. Новая услуга.yaml просто имеет несколько из них (до сих пор):
App:
resource: '../src/*'
# Controllers
AppController:
resource: '../src/Controller'
autowire: true
public: true
tags: ['controller.service_arguments']
# Models
AppModel:
resource: '../src/Model/'
autowire: true
public: true
// etc
вопрос: Вам действительно нужно добавить определения служб в службы.yaml для сторонних классов поставщиков? И если да, могу ли я получить пример того, как это сделать, пожалуйста? Любые советы от тех, кто уже обновился от Symfony 3 to в Symfony 4 было бы здорово.
PHP 7.2.0-2 + ubuntu16.04.1+deb.sury.org+2 (cli) (построено: 7 декабря 2017 20:14: 31) ( NTS ) Linux Mint 18, Apache2 Ubuntu.
EDIT / FYI:
это " доктринаORMEntityRepository::_ _ construct ()", которую ActivationRepository расширяет:
/**
* Initializes a new <tt>EntityRepository</tt>.
*
* @param EntityManager $em The EntityManager to use.
* @param MappingClassMetadata $class The class descriptor.
*/
public function __construct(EntityManagerInterface $em, MappingClassMetadata $class)
{
$this->_entityName = $class->name;
$this->_em = $em;
$this->_class = $class;
}
который находится здесь:
/vendor/doctrine/orm/lib/Doctrine/ORM/EntityRepository.php
2 ответов
начиная с версии 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);
}
// ...
}
вам действительно нужно добавить определения служб в службы.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.
}
никаких других шагов не требуется.