У меня есть небольшая внешняя библиотека, в которой есть много классов.
В моем проекте 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, не объявляя каждую службу?
Спасибо
Хорошо, не могли бы вы привести пример того, что считаете, что эту проблему следует решить? Спасибо @FabienPapet
Похоже, ваш первый подход должен был сработать. Вернитесь к нему, затем запустите «bin / console debug: container» и посмотрите, есть ли у вас вообще какие-либо службы ExternalLibrary. Возможно, вам придется закомментировать строки для пространства имен App, чтобы избежать исходной ошибки.
@Cerad проблема в том, что я автоматически подключаю интерфейс и должен быть объявлен с псевдонимом, например
И я почти уверен, что вам нужно будет сделать интерфейс ExternalLibrary \ Domain \ Model \ Repository псевдонимом ExternalLibrary \ Domain \ Model \ Lotto \ Repository. Наши комментарии пересеклись. autowire мало помогает с интерфейсами. См. В качестве примера последнюю часть ответа ниже.
Да, в этом и заключалась проблема @Cerad






Вам нужно создать сервисы вручную: Я не тестировал, но это должно выглядеть так
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."}'
"так далее." Было бы все, что не нужно в качестве сервиса.
Не уверен, что загрузка всего каталога - хорошая идея. это может повлиять на процесс создания контейнера. В любом случае, для каждого интерфейса в аргументах конструктора вам необходимо вручную объявить класс или псевдоним.