Symfony如何在我的服务中获取容器

时间:2017-08-30 16:17:33

标签: php symfony design-patterns inversion-of-control 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()。

3 个答案:

答案 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;
    }
}