【问题标题】:Accessing container outside of controller but not able to inject a service访问控制器外部的容器但无法注入服务
【发布时间】:2016-12-02 05:08:36
【问题描述】:

由于我使用某些类的方式,我无法进行服务注入,但我需要访问其中的服务容器。

namespace DocumentsUploadSystem;

use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerAwareTrait;

class DocumentsUpload implements ContainerAwareInterface
{
    use ContainerAwareTrait;

        public function getData()
    {
        var_dump($this->container);
    }

}

如果我像这样从控制器调用此方法。

use DocumentsUploadSystem\DocumentsUpload
...

$x = new DocumentsUpload($request)->getData();

我没有收到任何错误,但容器返回为空。这是实现 ContainerAwareInterface 的错误方法吗?我正在使用 Symfony 3.1

【问题讨论】:

  • 解释你是如何使用某些类而不能够进行服务注入的。原则上,服务注入总是可行的。
  • 因为我在控制器中将这些类实例化为变量,并使用 __construct 将变量传递给这些类。

标签: php symfony


【解决方案1】:

但是在这个例子中 [https://symfony.com/doc/current/bundles/KnpMenuBundle/index.html] 他们使用相同的技术并且可以很好地访问容器,它在那里工作,在其他地方调用服务吗?

// src/AppBundle/Menu/Builder.php
namespace AppBundle\Menu;

use Knp\Menu\FactoryInterface;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerAwareTrait;

class Builder implements ContainerAwareInterface
{
    use ContainerAwareTrait;

    public function mainMenu(FactoryInterface $factory, array $options)
    {
        $em = $this->container->get('doctrine')->getManager();
    }
}

【讨论】:

  • 之所以有效,是因为 KnpMenuBundle 会自动创建菜单并为您注入容器。见github.com/KnpLabs/KnpMenuBundle/blob/master/Provider/…
  • 好的,这是有道理的。谢谢 craigh,那个 sn-p 实际上帮了我很多。
  • 我已经更新了我的答案。如果你能接受,那就太好了。谢谢。
【解决方案2】:

实现一个接口不会做任何事情。接口是类的构建者和类的用户之间的契约,保证某些方法的存在——仅此而已。在这种情况下,ContainerAwareInterface 保证setContainer() 方法可用。然后您必须使用它来设置您的容器。

// MyController extends Symfony\Bundle\FrameworkBundle\Controller\Controller
use DocumentsUploadSystem\DocumentsUpload
...

$x = new DocumentsUpload($request);
$x->setContainer($this->container);
$xData = $x->getData();

为了记录,我不建议注入整个容器 - 只注入完成任务所需的实际服务。

KnpMenuBundle 之类的库似乎正在使用它,但实际上,它们正在自动创建菜单并为您注入容器。见https://github.com/KnpLabs/KnpMenuBundle/blob/master/Provider/BuilderAliasProvider.php#L122-L124

祝你好运!

【讨论】:

  • 但是有没有办法在不注入的情况下访问类中的容器?
  • 没有。你不能访问你一开始就没有放在那里的东西。
  • 诅咒你可以在不注入容器的情况下访问容器。但如何做到这一点是一个很大的秘密。即使您搜索“访问控制器外部的容器”,即使谷歌也不会给您答案。我认为它是机密或什么的。
  • craigh 为什么不建议注入整个容器?我读得更频繁,但我看不出有什么原因。请记住,类是通过引用传递的。另一点是,如果您的类中需要多个服务,则只需注入整个容器即可,而不是在构造函数中使用两个或多个参数
  • @FrankB - 搜索“依赖注入与服务定位器”,详细了解每种方法的优缺点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-22
  • 1970-01-01
  • 2015-12-07
  • 2017-03-13
  • 1970-01-01
相关资源
最近更新 更多