Я использую компонент Symfony Dependency Injection версии 3.4 в моем пользовательском проекте PHP. Мой проект работает на PHP 5.6
"symfony/dependency-injection": "^3.4"
Я определил свой файл services.yaml таким образом, чтобы он содержал следующие определения служб
logger:
class: Monolog\Logger
arguments: ["application"]
autowire: true
public: true
Monolog\Logger: '@logger'
plugin_context:
class: MyProject\PluginContext
autowire: true
public: true
Я могу подтвердить, что автозагрузка работает и экземпляры обоих классов присутствуют в определении, но класс Logger не подключается автоматически в конструкторе PluginContext. класс определен в следующем коде
use Monolog\Logger;
class PluginContext
{
private $logger;
function __construct(Logger $logger) {
$this->logger = $logger;
}
}
Когда выполняется следующий код, PHP выдает исключение
$container->get("plugin_context");
Catchable fatal error: Argument 1 passed to MyProject\PluginContext::__construct() must be an instance of Monolog\Logger, none given
Ответ @ Smaine ниже о подсказке типа для LoggerInterface верен. Если вы собираетесь использовать autowire, вам необходимо иметь достаточно глубокое понимание того, как это работает, что означает чтение и понимание документы. И научиться использовать такие команды, как «bin / console debug: container --show-private | grep logger», чтобы узнать, какие службы и псевдонимы доступны.






Похоже, что либо содержимое services.yaml не заполнено.
Ваш файл услуг должен быть таким
services:
logger:
class: Monolog\Logger
arguments: ["application"]
autowire: true
public: true
Monolog\Logger: '@logger'
plugin_context:
class: MyProject\PluginContext
autowire: true
public: true
Измените свой FQCN $logger и используйте этот use Psr\Log\LoggerInterface вместо Monolog\Logger
Другое дело, благодаря автонастройке вам не нужно ничего указывать в service.yaml, кроме этого (конфигурация по умолчанию):
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
public: false # Allows optimizing the container by removing unused services; this also means
# fetching services directly from the container via $container->get() won't work.
# The best practice is to be explicit about your dependencies anyway.
# 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/{Entity,Migrations,Tests,Kernel.php}'
Док сказал: «Псевдонимы используются основными пакетами, чтобы разрешить автоматическое подключение сервисов. Например, MonologBundle создает службу с идентификатором регистратора. Но он также добавляет псевдоним: Psr \ Log \ LoggerInterface, который указывает на службу регистратора. Вот почему аргументы, типизированные с помощью Psr \ Log \ LoggerInterface, могут быть автоматически подключены », поэтому в вашем случае Psr \ Log \ LoggerInterface является псевдонимом для Monolog https://symfony.com/doc/current/service_container/autowiring.html#using-aliases-to-enable-autowiring
Я использую только компонент Symfony Dependency Injection, и мой проект не основан на фреймворке Symfony. Кроме того, почему я должен использовать LoggerInterface вместо Monolog?
С интерфейсом работать проще, и многие компоненты в Symfony, использующие автоподключение, должны использоваться с интерфейсом symfony.com/doc/current/service_container/….
Спасибо, я полностью согласен с тем, что вы сказали об использовании интерфейсов, но autowire также должен работать с конкретными классами, такими как Monlog ?.
Очень хороший вопрос. Мне нужно время, чтобы глубже изучить компонент DependencyInjection.
отсутствует
arguments: ["Monolog\Logger"]дляplugin_context:? похоже, что вашему конструктору требуется зависимость от регистратора, но она не определена в аргументах содержимого плагина