Я не могу понять, как работает Dependency Injection для пользовательских сервисов в SF 4.3 и PHP 7.2
В контроллере этот простой код сбрасывает правильно инициализированный объект Logger:
use Psr\Log\LoggerInterface;
/**
* @Route("/mytest", name="default_mytest")
*/
public function MyTestLoggerAction(LoggerInterface $logger) {
dump($logger);
return $this->render('default/index.html.twig');
}
Но в пользовательском сервисе Guards в Guards.php $ 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.
- добавление @required в getLogger () и установка public в true в services.yml, $ logger всегда null.
- с использованием публичной функции isValid (LoggerInterface $ logger), но всего кодакто запрашивает этот метод isValid возвращает «Слишком мало аргументов для функции isValid ()»
- с использованием __contruct (LoggerInterface $ logger), но везде, где мне нужен этот класс, код возвращает «Слишком мало аргументов для функции __construct () "
Первое редактирование
my services.yaml
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
и добавить в мой Guards.php
private $logger;
/**
* @required
*/
public function setLogger(LoggerInterface $logger) {
$this->logger = $logger;
}
public function isValid() {
dump($this->logger);
}
но безуспешно. Я всегда сбрасываю нулевое значение.
2nd Edit
Я вызываю службу Guard из EventSubscriberInterface, который прослушивает событие Wokflow:
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 (или любой другойсервис) в каждом классе мне нужно без написания тонны кодов с большим количеством установщиков.
Спасибо за вашу помощь.
Решение
Внедрение зависимостине работает с таким заводским вызовом.