Я хочу, чтобы Psr\Log\LoggerInterface был общедоступным в symfony, чтобы иметь возможность получить его прямо из контейнера с помощью $container->get('Psr\Log\LoggerInterface').
Я пробовал следующее services.yaml:
_defaults:
public: true
Psr\Log\LoggerInterface:
public: true
Psr\Log\LoggerInterface:
alias: 'logger'
public: true
Psr\Log\LoggerInterface:
alias: 'monolog.logger'
public: true
Я не могу понять, почему так сложно переписать сервис.




Использование $контейнер->получить() — плохая практика. Это нарушает многие хорошие принципы проектирования программного обеспечения.
Вместо этого вы должны использовать инъекцию конструктора.
class Foo
{
protected $logger;
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
}
}
Как отмечалось ранее, прямой доступ к службам из контейнера не рекомендуется. Но мне было немного любопытно посмотреть, как сделать частную службу общедоступной. Я попробовал то, что было указано в вопросе, и подтвердил, что это не сработало.
Это может быть не самый простой подход, но проход компилятора поможет:
# src/Kernel.php
# Make the kernel a compiler pass
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
class Kernel extends BaseKernel implements CompilerPassInterface
...
public function process(ContainerBuilder $container)
{
$logger = $container->getAlias(LoggerInterface::class);
$logger->setPublic(true);
}
# And that should do the trick, you can confirm with
bin/console debug:container Psr\Log\LoggerInterface
Имейте в виду, что только сервисы, в которых внедрен полный контейнер, смогут воспользоваться этим. Контроллеры, унаследованные от AbstractController, имеют доступ только к небольшому количеству сервисов.
Взгляните на Подписчики услуг, если вам нужен регистратор в вашем контроллере или если вам просто нужен «лучший» способ сделать это.
Все говорят, что использование контейнера напрямую — плохая практика. Однако два момента. Никто не знает моих ситуаций. А во-вторых, никто не удосужился объявить параметры конструктора службы, которая на самом деле этой службе не нужна, но предназначена для ее дочерней службы.
Если очень хочется знать, зачем мне это нужно, я разработал пакет для удобных опций - github.com/mrself/php-параметры. У него нет документации. Но вскоре вы объявляете свойство следующим образом: ` /** * @Option() * @var CategoryRepository */ protected $categoryRepository; ` и у вас есть репозиторий после инициализации класса.
Для справки, я сказал «не рекомендуется», а не «плохо», потому что, конечно, бывают случаи, когда необходим доступ к контейнеру. Не уверен, что именно делает ваш пакет опций из вашего комментария. Просто для информации, есть аннотация /** @required */, которую можно использовать для автоматического внедрения зависимостей. Вы даже можете поместить его в трейт, и тогда любой класс, который использует трейт, получит зависимость без дополнительных усилий.
@required звучит интересно. Вы имеете в виду этот php-di.org/doc/annotations.html ?
Неправильный контейнер. Честно говоря, я не знаю, где именно это задокументировано. Несколько раз смотрел, но не нашел. Было обсуждение здесь. И здесь — это рабочий пример того, как он используется для внедрения маршрутизатора в RouterTrait. Затем вы можете использовать RouterTrait в любой другой службе, которой нужна возможность маршрутизации, не беспокоясь о внедрении маршрутизатора. Немного волшебно, но я нахожу это полезным.
Было бы избыточно иметь типаж для каждой службы. DI @Inject очень мощный. Мой пакет делает то же самое. Однако я разочарован тем, что не встретил DI раньше. Попробую заменить этот код на DI
Это прекрасно. Но опять же, имейте в виду, что контейнер Symfony не поддерживает все аннотации, которые поддерживает контейнер PHP_DI. Две совершенно разные кодовые базы. Я не думаю, что @Inject доступен из коробки. Не уверен, что вы подразумеваете под «избыточным». Я делаю трейты только для наиболее часто используемых сервисов. В противном случае я просто использую инъекцию конструктора. Но удачи.
Этот код все еще применяется для 3.4 и более поздних версий? Я добавил в свой appKernel.php (я переношу старое приложение 2.7) и проверил его запуск в отладчике, но, несмотря на установку общедоступного параметра, при следующем запросе службы он все еще находится в списке частных служб. РЕДАКТИРОВАТЬ - да, мне просто нужно было изменить имя службы на "логгер", т.е. $container->getAlias('logger'). О, так просто!
Большое спасибо, SteveChilds (и, конечно же, Cerad). Другая ситуация, когда это может потребоваться, — это когда у вас есть устаревший код, в котором вы не можете использовать D-I.
$container->get('logger') получит регистратор, если у вас есть доступ ко всему контейнеру. Вы пытаетесь получить доступ к регистратору с контроллера или просто с какого-то сервиса?