我有symfony项目,在这个项目中,我有自己的大型服务,这些服务庞大而复杂,有自己的依赖等等......
我想为此服务创建facade,目的是在controllers
中使用我的服务,如:
$myService = $this->container->get('service_from_my_domain');
我的问题 - 我的外观如何能够访问container
以获取服务的依赖关系。我只知道一种方法 - 是在yaml配置中将依赖注入服务。
但是还有另一种方法吗?像:
$dependency = Container::getInstance()->get('my_dependency_service');
我找到this answer但是使用全局变量感觉就像回到过去一样......
PS:我不想通过yaml配置注入依赖(不是构造函数注入也不是setter注入)因为我不需要IoC(inversion-of-control)。
答案 0 :(得分:4)
services:
kernel.listener.acme_listener:
class: Acme\AcmeBundle\EventListener\AcmeListener
arguments:
- @service_container
tags:
- { name: kernel.event_listener, event: kernel.controller, method: onKernelController }
你的听众
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
class AcmeListener
{
/**
* @var Container
*/
private $container;
/**
* Constructor
*
* @param Container $container
*/
public function __construct(Container $container)
{
$this->container = $container;
}
public function onKernelController(FilterControllerEvent $event)
{
$this->container->...
}
}
答案 1 :(得分:0)
如果你真的想要玩得开心并做代码逃脱,你可以做这样的事情......
创建一个Facade
类,必须在应用启动时初始化。因此,在app.php
中,在$kernel = new AppKernel('prod', false);
行进行Facade
初始化之后:
$kernel->boot();
$container = $kernel->getContainer();
\MyBundle\Facade::init($container);
并且,这是Facade
类的代码:
<?php
namespace MyBundle;
use Symfony\Component\DependencyInjection\ContainerInterface;
class Facade
{
/**
* self|null
*/
private static $instance = null;
/**
* ContainerInterface
*/
private static $myContainer;
/**
* @param ContainerInterface $container
*/
private function __construct(ContainerInterface $container)
{
self::$myContainer = $container;
}
/**
* @param string $serviceId
*
* @return object
* @throws \Exception
*/
public static function create($serviceId)
{
if (null === self::$instance) {
throw new \Exception("Facade is not instantiated");
}
return self::$myContainer->get($serviceId);
}
/**
* @param ContainerInterface $container
*
* @return null|Facade
*/
public static function init(ContainerInterface $container)
{
if (null === self::$instance) {
self::$instance = new self($container);
}
return self::$instance;
}
}
而且,无论您需要某项服务,都可以通过以下方式创建:
$service = \MyBundle\Facade::create('my_dependency_service');
但是,如果你问我 - 我会创建一个Facade服务,它会在构造函数中注入一个容器。
你会有一些服务创建方法(Facade::create($serviceId)
),它会向容器询问给定的服务ID。
答案 2 :(得分:0)
我使用 Symfony 5 构建了一个控制台应用程序。
在 Symfony 5 中注入服务就像 __construct(ServiceClass $service_name)
(类型提示)一样简单,一切都是服务。但在一种情况下,我无法在构造函数中进行依赖注入,因为依赖服务以命令行中给出的参数为条件。
这就是我动态注入所需服务的方式。
<?php
namespace App\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use App\Kernel;
class MyCommand extends Command {
protected static $defaultName = 'app:my-command';
private $container;
public function __construct(Kernel $kernel) {
$this->container = $kernel->getContainer();
//...
parent::__construct();
}
protected function configure() {
// ...
}
protected function execute(InputInterface $input, OutputInterface $output) {
//...
// read the parameters given in the cmd and decide what class is
// gona be injected.
// $service_name = "App\\My\\Namespace\\ServiceClassName"
$service = $this->container->get($service_name);
$service->doSomething();
return Command::SUCCESS;
}
}