Dependency injection 定制服务中记录器的依赖注入

Dependency injection 定制服务中记录器的依赖注入,dependency-injection,workflow,symfony4,php-7.2,Dependency Injection,Workflow,Symfony4,Php 7.2,我无法理解SF4.3和PHP7.2中的依赖注入是如何用于定制服务的 在控制器中,此简单代码转储正确初始化的对象记录器: use Psr\Log\LoggerInterface; /** * @Route("/mytest", name="default_mytest") */ public function MyTestLoggerAction(LoggerInterface $logger) { dump($logger); return $this->rend

我无法理解SF4.3和PHP7.2中的依赖注入是如何用于定制服务的

在控制器中,此简单代码转储正确初始化的对象记录器:

use Psr\Log\LoggerInterface;

/**
 * @Route("/mytest", name="default_mytest")
 */
public function  MyTestLoggerAction(LoggerInterface $logger) {
    dump($logger);

    return $this->render('default/index.html.twig');
}
但在Guards.php中名为Guards的定制服务中,$logger是空值:

namespace App\Workflow\CompanyDeploying\Transitions\Guards;

use Psr\Log\LoggerInterface;

class Guards {

    private $logger;

    public function setLogger(LoggerInterface $logger) {
        $this->logger = $logger;
    }

    public function isValid() {
        dump($this->logger);
    }
}
我试过:

  • 使用LoggerAwareTrait,但不会发生更多情况,$logger始终为null
  • 在getLogger()上添加@required并在services.yml中将public设置为true,$logger始终为null
  • 使用公共函数isValid(LoggerInterface$logger),但请求此isValid方法的所有代码都返回“函数isValid()的参数太少”
  • 使用_construct(LoggerInterface$logger),但在任何需要此类的地方,代码都会返回“函数_construct()的参数太少”
第一次编辑

我的服务,亚马尔先生

services:
    # default configuration for services in *this* file
    _defaults:
        autowire:      true # Automatically injects dependencies in your services.
        autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
        public: false

    # makes classes in src/ available to be used as services
    # this creates a service per class whose id is the fully-qualified class name
    App\:
        resource: '../src/*'
        exclude:  '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'

    # controllers are imported separately to make sure services can be injected
    # as action arguments even if you don't extend any base controller class
    App\Controller\:
        resource: '../src/Controller'
        tags:     ['controller.service_arguments']

    # add more service definitions when explicit configuration is needed
    # please note that last definitions always *replace* previous ones
    App\EventListener\CompanyIndexer:
        tags:
            - { name: doctrine.event_listener, event: prePersist }
App\Workflow\CompanyDeploying\Transitions\Guards\Guards:
    autowire:      true
    autoconfigure: true
    public:        true
我试图在services.yaml中强制autowire、autoconfig和可见性

services:
    # default configuration for services in *this* file
    _defaults:
        autowire:      true # Automatically injects dependencies in your services.
        autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
        public: false

    # makes classes in src/ available to be used as services
    # this creates a service per class whose id is the fully-qualified class name
    App\:
        resource: '../src/*'
        exclude:  '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'

    # controllers are imported separately to make sure services can be injected
    # as action arguments even if you don't extend any base controller class
    App\Controller\:
        resource: '../src/Controller'
        tags:     ['controller.service_arguments']

    # add more service definitions when explicit configuration is needed
    # please note that last definitions always *replace* previous ones
    App\EventListener\CompanyIndexer:
        tags:
            - { name: doctrine.event_listener, event: prePersist }
App\Workflow\CompanyDeploying\Transitions\Guards\Guards:
    autowire:      true
    autoconfigure: true
    public:        true
并添加myguards.php

private $logger;

/**
 * @required
 */
public function setLogger(LoggerInterface $logger) {
    $this->logger = $logger;
}

public function isValid() {
    dump($this->logger);
}
但是没有成功。我总是转储空值

第二次编辑

我从正在收听Wokflow事件的EventSubscriberInterface调用警卫服务:

public static function getSubscribedEvents()
{
    return [
        'workflow.company_deploying.enter.mystate' => 'onEnter',
        'workflow.company_deploying.leave.mystate' => 'onLeave',
        'workflow.company_deploying.guard.mystate' => 'guardMyTransition',
    ];
}

public function guardMyTransition(Event $event) {
    $this->event = $event;

    if (! $this->guardFactory(__FUNCTION__)->isValid()) {
        $event->setBlocked(true);
    }
}

protected function guardFactory($guardName) {

    $guard = GuardsFactory::create($guardName);

    $guard->setCompany($this->event->getSubject());
    if (isset($this->entityManager)) $guard->setEntityManager($this->entityManager);
    if (isset($this->previousState)) $guard->setPreviousState($this->previousState);
    return $guard;        
}
我的GuardFactory初始化一个子类Guards

在var/cache中,我有一个getGuardService.php

use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;

// This file has been auto-generated by the Symfony Dependency Injection Component for internal use.
// Returns the public 'App\Workflow\CompanyDeploying\Transitions\Guards\Guards' shared autowired service.

include_once $this->targetDirs[3].'/src/Workflow/CompanyDeploying/Transitions/Guards/Guards.php';

$this->services['App\\Workflow\\CompanyDeploying\\Transitions\\Guards\\Guards'] = $instance = new \App\Workflow\CompanyDeploying\Transitions\Guards\Guards();

$instance->setLogger(($this->privates['monolog.logger'] ?? $this->getMonolog_LoggerService()));

return $instance;
我只需要在我需要的每个类中轻松地使用$logger(或任何其他服务),而无需使用大量setter编写大量代码

谢谢你的帮助

解决方案


依赖项注入不适用于这种工厂调用。

您的服务可能不是自动连接的。如果此服务已加载到DI容器中,并且是自动连接和自动配置的,请检入services.yaml。谢谢您的回答。我在原始帖子中添加了我的services.yaml以及我为“强制”autowire和autoconfigure所做的事情。您如何使用Guard服务?如果服务被正确实例化并且为您的服务调用了
setLogger
方法(您应该查找
getguardservice.php
文件),您可以检查
var/cache
目录吗?再次感谢您的回答。我编辑了我的帖子,以添加您要求的详细信息。对于这个问题,我有两种方法:从事件调用并使用子类而不是主类OK,假设在
GuardFactory::create
中调用的是
new-Guard
,那么调用服务的方式是错误的:通过构造函数调用,依赖服务不会被注入。您需要一个服务容器来为您创建
Guard
实例。例如,在事件订阅服务器中,您可以注入保护服务、容器接口(保护服务设置为公共)或从
服务容器
服务调用保护服务的非静态保护工厂。您的服务可能不是自动连接的。如果此服务已加载到DI容器中,并且是自动连接和自动配置的,请检入services.yaml。谢谢您的回答。我在原始帖子中添加了我的services.yaml以及我为“强制”autowire和autoconfigure所做的事情。您如何使用Guard服务?如果服务被正确实例化并且为您的服务调用了
setLogger
方法(您应该查找
getguardservice.php
文件),您可以检查
var/cache
目录吗?再次感谢您的回答。我编辑了我的帖子,以添加您要求的详细信息。对于这个问题,我有两种方法:从事件调用并使用子类而不是主类OK,假设在
GuardFactory::create
中调用的是
new-Guard
,那么调用服务的方式是错误的:通过构造函数调用,依赖服务不会被注入。您需要一个服务容器来为您创建
Guard
实例。例如,在事件订阅服务器中,您可以注入保护服务、容器接口(保护服务设置为public)或从
服务容器
服务调用保护服务的非静态保护工厂。