Dependency injection 定制服务中记录器的依赖注入
我无法理解SF4.3和PHP7.2中的依赖注入是如何用于定制服务的 在控制器中,此简单代码转储正确初始化的对象记录器: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
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)或从服务容器
服务调用保护服务的非静态保护工厂。