Не удается выполнить сервис autowire в Symfony

Я пытаюсь разделить один большой service.yaml на несколько файлов меньшего размера. В origin service.yaml у меня было

Сервисы:

_defaults:
    autowire: true
    autoconfigure: true
    public: false

App\Domain\Country\Infrastructure\Repository\CountryRepository:
    public: true
    class: App\Domain\Country\Infrastructure\Repository\CountryRepository
    factory: ["@doctrine.orm.default_entity_manager", getRepository]
    arguments: [App\Domain\Country\Entity\Country]

Затем я добавил импорт в начало service.yam

imports:
  - {resource: services/repositories.yaml}

repositories.yaml

services:
    _defaults:
        autowire: true
        autoconfigure: true
        public: true

     App\Domain\Country\Infrastructure\Repository\CountryRepository:
        factory: ["@doctrine.orm.default_entity_manager", getRepository]
        arguments: [App\Domain\Country\Entity\Country]

После этого я начал получать ошибку

  Cannot autowire service "App\Domain\Country\Infrastructure\Repository\Count  
  ryRepository": argument "$class" of method "Doctrine\ORM\EntityRepository::  
  __construct()" references class "Doctrine\ORM\Mapping\ClassMetadata" but no  
   such service exists.  

Что там не так?

удалить _defaults из repositories/yaml. Также сделайте отступ App\Domain\Country\Infrastructure\Repository\CountryReposito‌​ry

Pmpr 16.11.2018 12:17

спасибо, но то же самое :(

akor 16.11.2018 12:21

Отредактируйте свой вопрос и поместите новые файлы

Pmpr 16.11.2018 12:22

Я добавил ссылку на pastebin

akor 16.11.2018 12:25

Версия Symfony?

Pmpr 16.11.2018 12:27

последний. Symfony 4

akor 16.11.2018 12:33

Если вы используете автоматическое подключение, вам вообще нужно предоставить определение репо? Достаточно просто иметь его в качестве аргумента конструктора ... Просто убедитесь, что у вашего объекта Country есть аннотация репозитория для класса CountryRepository

OK sure 16.11.2018 12:48

потому что я использую одну стороннюю библиотеку, куда я отправлял контейнер напрямую для таких запросов. Наверное, можно по-другому сделать? $ repository = $ this-> container-> get ('App \ Domain \ Billing \ Counterparty \ Infra‌ structure \ Repository‌ \ CounterpartyReposit‌ ory'); return $ repository-> getById ($ input);

akor 16.11.2018 12:58

Вам следует избегать отправки всего контейнера целиком. Но это, вероятно, сработает. В какой-то момент вы можете столкнуться с рекурсивными проблемами, особенно если вы начнете использовать запрос и т. д. Я бы постарался избежать отправки всего контейнера в какой-либо класс.

OK sure 16.11.2018 13:02

Да, я знаю, что это плохая практика :( Но я понятия не имею, как обернуть стороннюю библиотеку для поддержки DI

akor 16.11.2018 13:05

Внедрить стороннюю библиотеку в службу вместе с любыми другими зависимостями и использовать ее изолированно, а не пытаться подключить ее извне.

OK sure 16.11.2018 13:10

позволь мне проверить, но это не быстро

akor 16.11.2018 13:13

@akor - все файлы yaml в config / services.yaml автоматически загружаются Kernel.php, поэтому нет необходимости в явном импорте. Сообщение об ошибке исходит не из вашей конфигурации. Скорее у вас есть что-то еще, которое сканирует ваш каталог инфраструктуры и пытается создать службу из всего, что находит. Проверьте остальную часть настройки autowire и выясните, как исключить каталог. Или сделайте так, как предлагали другие, и просто расширите ServiceEntityRepository.

Cerad 16.11.2018 14:34

@akor ты нашел какое-нибудь решение?

Liauchuk Ivan 22.03.2019 17:08
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Symfony Station Communiqué - 17 февраля 2023 г
Symfony Station Communiqué - 17 февраля 2023 г
Это коммюнике первоначально появилось на Symfony Station , вашем источнике передовых новостей Symfony, PHP и кибербезопасности.
Управление ответами api для исключений на Symfony с помощью KernelEvents
Управление ответами api для исключений на Symfony с помощью KernelEvents
Много раз при создании api нам нужно возвращать клиентам разные ответы в зависимости от возникшего исключения.
4
14
24 583
2

Ответы 2

Вместо этого используйте именованные аргументы:

repositories.yaml

services:

     App\Domain\Country\Infrastructure\Repository\CountryRepository:
        factory: ["@doctrine.orm.default_entity_manager", getRepository]
        arguments:
            $class: '@App\Domain\Country\Entity\Country'

Внутри repositories.yaml. Когда у меня есть все объявления репозитория в services.yaml, он работает нормально. Но как только я разбиваю его, я получаю ошибку.

akor 16.11.2018 12:49

попробуйте переместить imports в самую верхнюю строку над параметрами

Pmpr 16.11.2018 12:57

Вам не нужно определять репозиторий для целей автоматического подключения.

services.yaml:

services:
    _defaults:
        autowire: true
        autoconfigure: true
        public: false

    App\:
        resource: '../src/*'
        exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'

    App\Controller\:
        resource: '../src/Controller'
        tags: ['controller.service_arguments']

Организация \ Страна:

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass = "App\Repository\CountryRepository")
 */
class Country
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type = "integer")
     */
    private $id;

    /**
     * @ORM\Column(type = "string", length=255)
     */
    private $name;

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getName(): ?string
    {
        return $this->name;
    }
}

Репозиторий \ CountryRepository:

<?php

namespace App\Repository;

use App\Entity\Country;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Symfony\Bridge\Doctrine\RegistryInterface;

/**
 * @method Country|null find($id, $lockMode = null, $lockVersion = null)
 * @method Country|null findOneBy(array $criteria, array $orderBy = null)
 * @method Country[]    findAll()
 * @method Country[]    findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
 */
class CountryRepository extends ServiceEntityRepository
{
    public function __construct(RegistryInterface $registry)
    {
        parent::__construct($registry, Country::class);
    }
}

И напоследок ваш сервис:

<?php

namespace App\Service;

use App\Repository\CountryRepository;

class ExampleService
{
    /**
     * @var CountryRepository
     */
    private $repository;

    /**
     * @param CountryRepository $repository
     */
    public function __construct(CountryRepository $repository)
    {
        $this->repository = $repository;
    }
}

Автоматическое подключение увидит, что вы внедрили этот CountryRepository в конструктор ExampleService, и обработает все остальное.

Ваш вариант попробую чуть позже. Но поправьте меня, будет ли это работать с $ repository = $ this-> container-> get ('App \ Domain \ Billing \ Counterparty \ Infra‌ structure \ Repository‌ \ CounterpartyReposit‌ ory'); ? Как в таком случае получить репозиторий из контейнера?

akor 16.11.2018 13:08

Это должно работать (или использовать префикс @ и использовать в определении службы), но, как уже упоминалось, звучит неприятно, потому что контейнер вводится. Трудно дать совет, не зная точной проблемы, но вы должны иметь возможность настроить свою стороннюю библиотеку и передать то, что вам нужно, вместо того, чтобы делать это.

OK sure 16.11.2018 13:13

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