В Sylius 1.11, после создания нового объекта Campaign с помощью пакета maker, я получаю эту ошибку при попытке получить кампанию, используя ее репозиторий:
Невозможно автоматически связать службу "App\Repository\CampaignRepository": аргумент "$class" метода "Doctrine\ORM\EntityRepository::__construct()" ссылается на класс "Doctrine\ORM\Mapping\ClassMetadata", но такой службы не существует.
Кажется, это код, который вызывает ошибку:
<?php
namespace App\Controller;
use App\Repository\CampaignRepository;
class CampaignController extends AbstractController {
protected CampaignRepository $repository;
public function __construct(CampaignRepository $repository) {
$this->repository = $repository;
}
public function details(string $id)
{
$campaign = $this->repository->find($id);
dd($campaign);
}
}
App\Repository\CampaignRepository существует и определяется следующим образом, что рекомендует документация Sylius:
<?php
namespace App\Repository;
use App\Entity\Campaign;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Sylius\Bundle\ResourceBundle\Doctrine\ORM\EntityRepository;
/**
* @extends ServiceEntityRepository<Campaign>
*
* @method Campaign|null find($id, $lockMode = null, $lockVersion = null)
* @method Campaign|null findOneBy(array $criteria, array $orderBy = null)
* @method Campaign[] findAll()
* @method Campaign[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class CampaignRepository extends EntityRepository
{
}
Как исправить эту ошибку?






Оказывается, Силиус довольно требователен как к подсказке типа, так и к имени переменной. Это связано с тем, как работает внедрение зависимостей Symfony и как Sylius решил его использовать.
Измените конструктор на:
public function __construct(
\Sylius\Component\Resource\Repository\RepositoryInterface $campaignRepository
) {
$this->repository = $campaignRepository;
}
Вам нужно использовать команду bin/console debug:container. Но если вы попытаетесь, вы столкнетесь с тем же сообщением об ошибке, что и при запуске действия вашего контроллера.
Что вам нужно сделать, это:
App\Controller\CampaignController::__construct())bin/console debug:container CampaignRepositorybin/console debug:container CampaignRepository
Select one of the following services to display its information:
[0] App\Repository\CampaignRepository
[1] Doctrine\Persistence\ObjectRepository $campaignRepository
[2] Doctrine\Common\Collections\Selectable $campaignRepository
[3] Sylius\Component\Resource\Repository\RepositoryInterface $campaignRepository
[4] Sylius\Bundle\ResourceBundle\Doctrine\ORM\EntityRepository $campaignRepository
[5] Doctrine\ORM\EntityRepository $campaignRepository
Sylius\Component\Resource\Repository\RepositoryInterface $campaignRepository, но любое из предложений с именем параметра должно работать)Если вам интересно, как это работает, посмотрите здесь: https://symfony.com/doc/current/service_container/autowiring.html#dealing-with-multiple-implementations-of-the-same-type
Я мог бы добавить, что основная проблема с вашим подходом заключается в том, что если вы добавите дополнительные методы в CampaignRepository, вы не сможете использовать методы в своем контроллере без жалоб IDE.
@Cerad В сообщении об ошибке никогда не упоминается ServiceEntityRepository. Я не пытался расширять ServiceEntityRepository , потому что в документации Sylius четко указано, что вы должны расширять EntityRepository . Если я сделаю то, что вы предлагаете, ошибка исчезнет, но игнорировать документы небезопасно.
Что касается завершения кода, приличные IDE позволяют переопределить обнаруженный тип переменной с помощью комментария. Пример: /** @var CampaignRepository $campaignRepository
Интересный. Ваша ссылка действительно меняет ServiceEntityRepository на EntityRepository. Sylius также должен сделать некоторые дополнительные настройки, потому что Symfony из коробки устанавливает ServiceEntityRepositoryFactory, который извлекает репозитории из сервисного контейнера. Так что да, работа с документацией, вероятно, лучшая идея.
В качестве подсказки типа вы можете использовать любой из интерфейсов, которые реализует класс репозитория, базовые, которые можно использовать для любого репозитория ресурсов, — это Sylius\Component\Resource\Repository\RepositoryInterface и Doctrine\Persistence\ObjectRepository. Для встроенных ресурсов Sylius существуют интерфейсы репозитория в компонентах более низкого уровня, а иногда и в основном компоненте, например Sylius\Component\Order\Repository\OrderRepositoryInterface и Sylius\Component\Core\Repository\OrderRepositoryInterface.
Плагины обычно также определяют интерфейсы.
Для пользовательских репозиториев в ваших проектах вам также следует определить интерфейсы, если вы добавляете пользовательские методы.
Имя аргумента также имеет значение.
Чтобы проверить, какие подсказки доступны, вместе с именем аргумента используйте команду bin/console debug:autowiring campaing.
можно добавить в файл services.yaml
your sercvice here -> the path of your file: autowire: true
или добавьте аргументы вручную
your sercvice here -> the path of your file: arguments:[....]
Спасибо за ваш ответ. Я знаю, как вручную связать аргументы с помощью symfony, но я не знаю, какое значение мне нужно связать для аргумента $class в этом конкретном контексте.
"Ваш сервис здесь" - что вы имеете в виду? Добавление строк, которыми вы поделились, должно вызвать серьезное сообщение об ошибке.
Вы случайно не пробовали, чтобы CampaignRepository расширял ServiceEntityRepository? Потому что это то, на что жалуется исходное сообщение об ошибке. Ваш класс App\Controller — единственный класс, использующий autowire. Другие сервисы имеют какую-то явную проводку.