web-dev-qa-db-ja.com

Symfony 3.4ロガーサービス

loggerサービスを呼び出したとき、ログファイルでこの情報メッセージを取得しましたが、動作しましたが、このメッセージをログファイルに書き込みます。

php.INFO:非推奨のユーザー:「ロガー」サービスはプライベートです。コンテナから取得することはSymfony 3.2以降では非推奨であり、4.0では失敗します。サービスを公開するか、コンテナの直接使用を停止して、代わりに依存性注入を使用する必要があります。 {"exception": "[object](ErrorException(code:0):User Deprecated:\" logger\"サービスはプライベートです。コンテナから取得することはSymfony 3.2以降廃止され、4.0では失敗します。サービスを公開するか、コンテナの使用を直接停止し、代わりに依存性注入を使用してください/home/****/###/PROJECT/vendor/symfony/symfony/src/Symfony/Component/DependencyInjection/Container.php:275 ) "} []

私のsymfonyバージョン:3.4.1

9
A.Seddighi

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

次に、サービスに依存関係を注入するには、コンストラクターに引数の型ヒントを追加します。

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

構成内の値をオーバーライドする代わりに、コンパイラパスでロガーをパブリックサービスとして設定することもできます。 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);
    }
}
21
fyrye

$this->container->get('logger')は、ロガーが(3.2の時点で)プライベートサービスとしてマークされ、すべてのサービスがデフォルトでプライベートであるため失敗します。つまり、これらのサービスはコンテナから返せず、依存関係を注入する必要があります(クラスコンストラクターは、ロガーをパラメーターとして取得し、アクセス可能なクラスのプロパティになるか、サービス構成でパブリックとしてマークする必要があります。ロガーはsymfonyコンポーネントであるため、サービス構成はsymfonyプロジェクト内にあります。コンテナからロガーインスタンスにアクセスするには、symfonyからプロジェクトサービス設定にロガー設定をコピーし、public: trueを追加する必要があります。

2
Yasha Nisanov