首页 文章

Symfony 3.4 Logger 服务

提问于
浏览
5

当我调用 logger service时,在日志文件中获取此信息消息它是否有效但是在日志文件中写入此消息:

php.INFO:User不推荐使用:“logger”服务是私有的,从容器中获取它自Symfony 3.2以来就已弃用,并且将在4.0中失败 . 您应该将服务公开,或者直接停止使用容器并改为使用依赖注入 . {“exception”:“[object](ErrorException(代码:0):用户不推荐使用:\”logger \“服务是私有的,从容器中获取它自Symfony 3.2以来就已弃用,并且将在4.0中失败 . 你应该制作服务公共,或者直接停止使用容器并改为使用依赖注入 . 在/home///####PROJECT/vendor/symfony/symfony/src/Symfony/Component/DependencyInjection/Container.php:275 )“} []

我的symfony版本:3.4.1

2 回答

  • 10

    $this->container->get('logger') 失败,因为logger现在(截至3.2)标记为私有服务,默认情况下所有服务都是私有的,这意味着这些服务不能从容器返回,而必须依赖注入(类构造函数必须采用logger作为参数并成为可访问类的属性,或在服务配置中标记为public,并且由于logger是symfony组件,服务配置在symfony项目中,您必须复制 Logger 从symfony配置到项目服务配置并添加 public: true ,以从容器访问 Logger 实例 .

  • 2

    如Symfony 3.4中所述, MonologBundle 和所有其他服务提供的 logger 服务默认设置为私有 . [sic]

    要解决此问题,建议的方法是使用依赖注入 . http://symfony.com/doc/3.4/logging.html

    namespace AppBundle/Controller;
    
    use Psr\Log\LoggerInterface;
    use Symfony\Bundle\FrameworkBundle\Controller\Controller;
    
    class DefaultController extends Controller
    {
         public function indexAction(LoggerInterface $logger)
         {
            $logger->info('Your Message');
         }
    }
    

    源代码参考:https://github.com/symfony/monolog-bundle/blob/v3.1.0/Resources/config/monolog.xml#L17

    对于服务定义,启用 autowire 时可以使用依赖注入 . [sic]

    #app/config/services.yml
    
    services:
        # default configuration for services in *this* file
        _defaults:
            # automatically injects dependencies in your services
            autowire: true
            # automatically registers your services as commands, event subscribers, etc.
            autoconfigure: true
            # this means you cannot fetch services directly from the container via $container->get()
            # if you need to do this, you can override this setting on individual services
            public: false
    
        # makes classes in src/AppBundle available to be used as services
        # this creates a service per class whose id is the fully-qualified class name
        AppBundle\:
            resource: '../../src/AppBundle/*'
            # you can exclude directories or files
            # but if a service is unused, it's removed anyway
            exclude: '../../src/AppBundle/{Entity,Repository,Tests}'
    
        #enables dependency injection in controller actions
        AppBundle\Controller\:
            resource: '../../src/AppBundle/Controller'
            public: true
            tags: ['controller.service_arguments']
    
       #all of your custom services should be below this line
       #which will override the above configurations
    
        #optionally declare an individual service as public
        #AppBundle\Service\MyService: 
        #    public: true
    
        #alternatively declare the namespace explicitly as public
        #AppBundle\Service\:
        #    resource: '../../src/AppBundle/Service/*'
        #    public: true
    

    然后,要将Dependency注入服务,请将参数的类型提示添加到构造函数中 .

    namespace AppBundle\Service;
    
    use Psr\Log\LoggerInterface;
    
    class MyService
    {
    
        private $logger;
    
        public function __construct(LoggerInterface $logger)
        {
             $this->logger = $logger;
        }
    
    }
    

    如果禁用 autowire ,则可以手动定义服务以注入 Logger 别名 .

    #app/config/services.yml
    
    services:
    
        AppBundle\Service\MyService:
            arguments: ['@logger']
            public: true
    

    或者,要强制从容器中公开访问 Logger 别名,您可以在应用程序服务配置中重新声明服务别名 .

    #app/config/services.yml
    
    services:
    
        #...
    
        logger:
            alias: 'monolog.logger'
            public: true
    

    您也可以在编译器传递中将logger设置为公共服务,而不是覆盖配置中的值 . https://symfony.com/doc/3.4/service_container/compiler_passes.html

    Symfony Flex

    // src/Kernel.php
    namespace App;
    
    use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
    use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
    use Symfony\Component\DependencyInjection\ContainerBuilder;
    use Symfony\Component\HttpKernel\Kernel as BaseKernel;
    
    class Kernel extends BaseKernel implements CompilerPassInterface
    {
        use MicroKernelTrait;
    
         public function process(ContainerBuilder $container)
         {
            // in this method you can manipulate the service container:
            // for example, changing some container service:
            $container->getDefinition('logger')->setPublic(true);
        }
    
    }
    

    Symfony Bundle

    // src/AppBundle/AppBundle.php
    namespace AppBundle;
    
    use Symfony\Component\HttpKernel\Bundle\Bundle;
    use Symfony\Component\DependencyInjection\ContainerBuilder;
    use AppBundle\DependencyInjection\Compiler\CustomPass;
    
    class AppBundle extends Bundle
    {
        public function build(ContainerBuilder $container)
        {
            parent::build($container);
    
            $container->addCompilerPass(new CustomPass());
        }
    }
    
    // src/AppBundle/DependencyInjection/Compiler/CustomPass.php
    namespace AppBundle\DependencyInjection\Compiler;
    
    use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
    use Symfony\Component\DependencyInjection\ContainerBuilder;
    
    class CustomPass implements CompilerPassInterface
    {
        public function process(ContainerBuilder $container)
        {
            $container->getDefinition('logger')->setPublic(true);
        }
    }
    

相关问题