Php 我怎样才能在Symfony收集所有独白记录者?

Php 我怎样才能在Symfony收集所有独白记录者?,php,symfony,monolog,Php,Symfony,Monolog,我有一个创建不同对象的工厂类,并且为每种类型的对象定义了许多记录器。 我想在我的工厂里收集所有的伐木工人。在此之前,我只是在工厂构造函数中使用ContainerInterface,但由于Symfony 5.1容器自动连接不受欢迎。 现在我找不到办法收集伐木工人。我试着用 !tagged_iterator { tag: 'monolog.logger' } 还尝试为LoggerInterface设置一个标记,并为其获取一个标记的迭代器,但没有成功。我认为这是因为记录器不是真正的类。这可能有些过分

我有一个创建不同对象的工厂类,并且为每种类型的对象定义了许多记录器。 我想在我的工厂里收集所有的伐木工人。在此之前,我只是在工厂构造函数中使用ContainerInterface,但由于Symfony 5.1容器自动连接不受欢迎。 现在我找不到办法收集伐木工人。我试着用

!tagged_iterator { tag: 'monolog.logger' }

还尝试为LoggerInterface设置一个标记,并为其获取一个标记的迭代器,但没有成功。我认为这是因为记录器不是真正的类。

这可能有些过分,但正如您所说,记录器服务有点不寻常。似乎它们应该被LoggerInterface标记或可标记,但我运行了一些测试,无法使其工作。以下是一种暴力方法,它依赖于ID为monolog.logger.name的记录器服务:

# Start with a service locator class
namespace App\Service;

use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\ServiceLocator;

class LoggerLocator extends ServiceLocator 
{
    // Just to specify the return type to keep IDEs happy
    public function get($id) : LoggerInterface
    {
        return parent::get($id);
    }
}
...

# now make the kernel into a compiler pass
# src/Kernel.php
class Kernel extends BaseKernel implements CompilerPassInterface
...
    public function process(ContainerBuilder $container)
    {
        $loggerServices = [];
        foreach($container->getServiceIds() as $id) {
            if (!strncmp($id,'monolog.logger.',15)) {
                //echo 'Logger ' . $id . "\n";
                $loggerServices[$id] = new Reference($id);
            }
        }
        $loggerLocator = $container->getDefinition(LoggerLocator::class);
        $loggerLocator->setArguments([$loggerServices]);
    }

# and now we can inject the locator where it is needed
class SomeController {
    public function index(Request $request, LoggerLocator $loggerLocator)
    {
        dump($loggerLocator);
        $logger = $loggerLocator->get('monolog.logger.' . $name);

似乎只有通过配置才能做到这一点,但我想传递过程非常简单。

实际上,将ContainerInterface别名添加到services.yaml并继续使用现有代码非常简单。但我理解重构的愿望。如果您事先知道实际的服务ID,那么我认为服务定位器可以做到这一点?@Cerad,我读过一篇文章,但还不明白它如何帮助我。请解释一下您的建议好吗?在您当前的代码中,您是否有几行$container->get('logger1')代码。在我的代码中,我们有一个协议,即配置中的记录器与工厂对象具有相同的名称,所以我只使用
$container->get('monog.logger')。strtolower($name))
MonogBundle将在中创建基于通道的记录器别名,而不是将其作为常规配置的一部分。因此,它们可能还不可用。您可以在自定义编译器类中收集它们,该类在Monolog中的编译器类之后运行。据我所知,您不必手动排定优先级,但请参见