【问题标题】:How to access Service container instance from anywhere?如何从任何地方访问服务容器实例?
【发布时间】:2014-07-29 17:41:08
【问题描述】:

好吧,我有 ZF2 的背景,但 Symfony 2 对我来说似乎有点奇怪...... 我关于服务的问题:

应该是服务是全球性的。为什么它们只能从控制器访问? 我们假设我有这样的事情:

src/Acme/AcmeBundle
   /Acme/SomeClass.php

如何从 SomeClass.php 访问 Container 服务(即:$this->get/$this->container)?

【问题讨论】:

  • 这就是 Symfony 的主要思想。只注入您需要的服务,使您的代码具有高度可测试性

标签: php symfony dependency-injection


【解决方案1】:

除非您有充分的理由这样做(非常罕见的情况),否则您根本不应该直接使用容器。从控制器内部访问容器只是为了方便,但我仍然认为这是一种不好的做法。

在大多数情况下,您应该将自定义类注册为依赖于框架、第 3 方捆绑包或您自己提供的特定服务的服务:

// your service

namespace Acme;

class SomeClass {
    private $serviceA;
    private $serviceB;
    private $param;

    public function __construct(A $serviceA, B $serviceB, $param = 0) {
        $this->serviceA = $serviceA;
        $this->serviceB = $serviceB;
        $this->param = $param;
    }

    public function doSth() {
        // ...
    }
}

// service definition for container

<service id="my_service" class="Acme\SomeClass">
    <argument type="service" id="some_service_a" />
    <argument type="service" id="some_service_b" />
    <argument>123</argument>
</service>

【讨论】:

  • 好的,我在文档中注意到了,但是.. 如何访问控制器之外的任何服务?
  • “外面”是什么意思?另一个,定制的课程?只需将其作为容器服务并添加依赖项作为构造函数参数,就像上面的示例一样。
  • 为什么会被接受和支持?它根本不回答问题,它只是提供建议和另一种方法:(
【解决方案2】:

你必须使用依赖注入。假设你有一个类 src/Acme/AcmeBundle/SomeClass.php 而不是 setContainer 函数

<?php

namespace Acme\AcmeBundle;

use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

class SomeClass implements ContainerAwareInterface
{

/**
 *
 * @var ContainerInterface
 */
protected $container;

/**
 * Sets the Container associated with this Controller.
 *
 * @param ContainerInterface $container A ContainerInterface instance
 */
 public function setContainer(ContainerInterface $container = null)
 {
  $this->container = $container;
 }

....
}

现在您可以将“SomeClass”定义为服务并像这样注入服务容器。

<service id="some.service.id" class="Acme\AcmeBundle\SomeClass">
      <call method="setContainer">
         <argument type="service" id="service_container"/>
      </call>
</service>

在此之后,“some.service.id”可以通过服务容器访问“SomeClass”,并将服务容器注入其中。

【讨论】:

  • 好的,我在文档中注意到了,但是.. 我怎样才能访问控制器之外的任何服务?
  • 您可以通过注入访问您的服务。您可以将服务容器或任何特定服务注入任何其他服务。
【解决方案3】:

几周前我写了一篇关于如何注入服务容器的帖子。

链接:- http://anjanasilva.com/blog/injecting-services-in-symfony-2/

顺便说一句,注入服务容器时要小心,因为这可能不是最好的方法。

希望这会有所帮助 问候

【讨论】:

  • 但是,再说一遍:只有控制器类可以访问容器。也就是说,我仍然无法从我的用户类 src/Acme/MyClass.php 中获得“database_conection”服务 - 例如 -
  • 然后注入教义 orm 管理器而不是服务容器。
猜你喜欢
  • 1970-01-01
  • 2010-11-08
  • 1970-01-01
  • 2017-02-27
  • 2012-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-01
相关资源
最近更新 更多