Symfony4 использует внешнюю библиотеку классов как услугу

У меня есть небольшая внешняя библиотека, в которой есть много классов.

В моем проекте symfony4 я хотел бы объявить свой класс от vendor как сервис с autowire и public. Итак, я включил свою библиотеку в composer и добавил такую ​​конфигурацию psr в composer.json:

"autoload": {
        "psr-4": {
            "App\\": "src/",
            "ExternalLibrary\\": "vendor/external-library/api/src/"
        }
    }

После этого я попытался заменить свой services.yaml на symfony вот так:

ExternalLibrary\:
    resource: '../vendor/external-library/api/src/*'
    public: true
    autowire: true

Если я запускаю тесты или запускаю приложение, мне возвращается эта ошибка:

Cannot autowire service "App\Domain\Service\MyService": argument "$repository" of method "__construct()" references interface "ExternalLibrary\Domain\Model\Repository" but no such service exists. You should maybe alias this interface to the existing "App\Infrastructure\Domain\Model\MysqlRepository" service.

Если я объявлю в services.yaml интерфейс, он будет работать нормально:

ExternalLibrary\Domain\Model\Lotto\Repository:
    class: '../vendor/external-library/api/src/Domain/Model/Repository.php'
    public: true
    autowire: true

Но у меня много классов, и я не хочу объявлять каждый класс, как я могу исправить services.yaml, не объявляя каждую службу?

Спасибо

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

Fabien Papet 04.09.2018 13:53

Хорошо, не могли бы вы привести пример того, что считаете, что эту проблему следует решить? Спасибо @FabienPapet

Alessandro Minoccheri 04.09.2018 13:53

Похоже, ваш первый подход должен был сработать. Вернитесь к нему, затем запустите «bin / console debug: container» и посмотрите, есть ли у вас вообще какие-либо службы ExternalLibrary. Возможно, вам придется закомментировать строки для пространства имен App, чтобы избежать исходной ошибки.

Cerad 04.09.2018 14:36

@Cerad проблема в том, что я автоматически подключаю интерфейс и должен быть объявлен с псевдонимом, например

Alessandro Minoccheri 04.09.2018 14:41

И я почти уверен, что вам нужно будет сделать интерфейс ExternalLibrary \ Domain \ Model \ Repository псевдонимом ExternalLibrary \ Domain \ Model \ Lotto \ Repository. Наши комментарии пересеклись. autowire мало помогает с интерфейсами. См. В качестве примера последнюю часть ответа ниже.

Cerad 04.09.2018 14:42

Да, в этом и заключалась проблема @Cerad

Alessandro Minoccheri 04.09.2018 15:01
Стоит ли изучать 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 и хотите разрабатывать...
8
6
2 415
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

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

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

services.yaml

Some\Vendor\:
    resource: '../vendor/external-library/api/src/*'
    public: true # should be false

Some\Vendor\FooInterface:
    alias: Some\Vendor\Foo # Interface implementation

Some\Vendor\Bar:
    class: Some\Vendor\Bar
    autowire: true

php

<?php

namespace Some\Vendor;

class Foo implements FooInterface
{

}

class Bar
{
    public function __construct(FooInterface $foo)
    {

    }
}

Если быть более точным, у вас должно получиться что-то вроде

ExternalLibrary\Domain\Model\Repository:
    alias: App\Infrastructure\Domain\Model\MysqlRepository

Возьмем для примера Dompdf:

Когда вы пытаетесь добавить подсказку типа Dompdf в свой контроллер действий или метод службы, произойдет ошибка, в которой говорится, что автоматическое подключение невозможно, потому что Dompdf - это внешнийБиблиотека PHP

Итак, чтобы решить эту проблему, мы внесем небольшие изменения в наш файл services.yaml, добавив этот короткий конфиг.

Dompdf\: #Add the global namespace
   resource: '../vendor/dompdf/dompdf/src/*' #Where can we find your external lib ?
   autowire: true  #Turn autowire to true

Примените приведенный выше пример ко всем внешним библиотекам PHP :)

Вот и все !

У меня была такая же проблема, и кто-то дал мне это решение, которое отлично работает для меня:

Используйте внешний репозиторий с проблемами symfony4 с автозагрузкой и параметрами

На всякий случай копирую другое решение пользователя @DasBen:

Я думаю, что вам не нужно импортировать каждую услугу отдельно. Вы уже делаете это с частью «Puc \ SapClient».

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

В примере проекта symfony есть эта часть vor "services.yaml":

# makes classes in src/ available to be used as services
  # this creates a service per class whose id is the fully-qualified class name
  App\:
    resource: '../src/*'
    exclude: '../src/{Bundle,DependencyInjection,Entity,Model,Migrations,Tests,Kernel.php}'

Тогда ваша часть будет:

# makes classes in src/ available to be used as services
  # this creates a service per class whose id is the fully-qualified class name
  Puc\SapClient\:
    resource: '../vendor/puc/sap-client/src/*'
    exclude: ''../vendor/puc/sap-client/src/{Entity,Model,"etc."}'

"так далее." Было бы все, что не нужно в качестве сервиса.

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