当我调用logger
服务时,在日志文件中获取此信息消息它可以工作但是在日志文件中写入此消息:
php.INFO:User Deprecated:“logger”服务 是私有的,从容器中获取它是自Symfony以来不推荐使用的 3.2并将在4.0中失败。您应该将服务公开,或者直接停止使用容器并使用依赖注入 代替。 {“exception”:“[object](ErrorException(code:0):User 不推荐使用:\“logger \”服务是私有的,从中获取它 自Symfony 3.2以来,容器已弃用,并且将在4.0中失败。您 应该使服务公开,或者停止使用容器 直接使用依赖注入。在 /home/****/###/PROJECT/vendor/symfony/symfony/src/Symfony/Component/DependencyInjection/Container.php:275)“} []
我的symfony版本:3.4.1
答案 0 :(得分:16)
如Symfony 3.4中所述,logger
和所有其他服务提供的MonologBundle
服务默认设置为私有。 [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
,您可以手动定义服务以注入记录器别名。
#app/config/services.yml
services:
AppBundle\Service\MyService:
arguments: ['@logger']
public: true
或者,要强制从容器中公开访问记录器别名,您可以在应用程序服务配置中重新声明服务别名。
#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);
}
}
答案 1 :(得分:2)
$this->container->get('logger')
失败,因为logger现在(截至3.2)标记为私有服务,默认情况下所有服务都是私有的,这意味着这些服务无法从容器返回,而必须依赖注入(类构造函数必须将记录器作为参数并成为可访问类的属性),或在服务配置中标记为公共,并且由于记录器是symfony组件,因此服务配置在symfony项目中,您必须将记录器配置从symfony复制到项目服务配置并添加public: true
,以便从容器中访问记录器实例。