Как исправить «Не удается выполнить автоподключение службы: аргумент ссылается на класс, но такой службы не существует» в Sylius?

В 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
{
}

Как исправить эту ошибку?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
0
73
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

TL;DR

Оказывается, Силиус довольно требователен как к подсказке типа, так и к имени переменной. Это связано с тем, как работает внедрение зависимостей Symfony и как Sylius решил его использовать.

Измените конструктор на:

public function __construct(
   \Sylius\Component\Resource\Repository\RepositoryInterface $campaignRepository
) {
    $this->repository = $campaignRepository;
}

Как ты должен это догадаться?

Вам нужно использовать команду bin/console debug:container. Но если вы попытаетесь, вы столкнетесь с тем же сообщением об ошибке, что и при запуске действия вашего контроллера.

Что вам нужно сделать, это:

  1. прокомментируйте любой метод, который использует функцию внедрения зависимостей symfony для доступа к экземпляру вашего репозитория (в нашем случае метод App\Controller\CampaignController::__construct())
  2. беги bin/console debug:container CampaignRepository
    Это вернет вам список услуг:
bin/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
  1. выбрал комбинацию имени класса и параметра для использования в качестве параметра конструктора (я выбрал Sylius\Component\Resource\Repository\RepositoryInterface $campaignRepository, но любое из предложений с именем параметра должно работать)
  2. раскомментируйте метод, который вы прокомментировали на шаге 1, и обновите его подпись
  3. вуаля

Если вам интересно, как это работает, посмотрите здесь: https://symfony.com/doc/current/service_container/autowiring.html#dealing-with-multiple-implementations-of-the-same-type

Вы случайно не пробовали, чтобы CampaignRepository расширял ServiceEntityRepository? Потому что это то, на что жалуется исходное сообщение об ошибке. Ваш класс App\Controller — единственный класс, использующий autowire. Другие сервисы имеют какую-то явную проводку.

Cerad 30.01.2023 16:30

Я мог бы добавить, что основная проблема с вашим подходом заключается в том, что если вы добавите дополнительные методы в CampaignRepository, вы не сможете использовать методы в своем контроллере без жалоб IDE.

Cerad 30.01.2023 17:22

@Cerad В сообщении об ошибке никогда не упоминается ServiceEntityRepository. Я не пытался расширять ServiceEntityRepository , потому что в документации Sylius четко указано, что вы должны расширять EntityRepository . Если я сделаю то, что вы предлагаете, ошибка исчезнет, ​​но игнорировать документы небезопасно.

nstCactus 30.01.2023 17:38

Что касается завершения кода, приличные IDE позволяют переопределить обнаруженный тип переменной с помощью комментария. Пример: /** @var CampaignRepository $campaignRepository

nstCactus 30.01.2023 17:43

Интересный. Ваша ссылка действительно меняет ServiceEntityRepository на EntityRepository. Sylius также должен сделать некоторые дополнительные настройки, потому что Symfony из коробки устанавливает ServiceEntityRepositoryFactory, который извлекает репозитории из сервисного контейнера. Так что да, работа с документацией, вероятно, лучшая идея.

Cerad 30.01.2023 18:54

В качестве подсказки типа вы можете использовать любой из интерфейсов, которые реализует класс репозитория, базовые, которые можно использовать для любого репозитория ресурсов, — это 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 в этом конкретном контексте.

nstCactus 06.02.2023 11:23

"Ваш сервис здесь" - что вы имеете в виду? Добавление строк, которыми вы поделились, должно вызвать серьезное сообщение об ошибке.

Nico Haase 06.02.2023 11:31

Другие вопросы по теме