将依赖注入容器传递给静态方法

Pat*_*ick 5 php symfony

我有一些传统课程。许多类是使用工厂类实例化的。

还有一个单例类。

将来我想用 DIC 完全替换它们。目前,代码库很大,无法做到这一点。

现在我的目标是将 DI-Container 注入到由 Singleton 类实例化的每个服务中。Singleton 类有一个带有此签名的静态方法。

final class Singleton
{
  private static $singletonCache = array();

  public static function getInstance($namespace, $className)
  {
  }
}
Run Code Online (Sandbox Code Playgroud)

在这个函数内部,我想检查:

$instance = new $className();

if($instance instanceof ContainerAwareInterface)
{
  // TODO: how do we get the container here
  $instance->setContainer($container);
}
Run Code Online (Sandbox Code Playgroud)

但是我怎样才能最好地将容器放入我的“单例类”中,它只是静态调用的?

Cer*_*rad 8

另一种方法是在需要时全局访问容器:

public static function getInstance($namespace, $className)
{
  $container = $_GLOBAL['kernel']->getContainer();
}
Run Code Online (Sandbox Code Playgroud)

当然,这种方法有一些问题,但只要你正在过渡,就足够了。

  • 这是有风险的,因为它还允许其他人从 $_GLOBAL 访问容器。在你试图清理的代码库中,你不应该打开新的混乱机会。 (2认同)

Jak*_*las 4

在引导代码早期的某个位置,但在实例化容器之后,您可以将容器传递给单例类:

Singleton::setContainer($container);
Run Code Online (Sandbox Code Playgroud)

它将容器存储在静态属性中:

final class Singleton
{
    // ...

    private static $container;

    public static function setContainer(ContainerInterface $container)
    {
        self::$container = $container;
    }
}
Run Code Online (Sandbox Code Playgroud)

然而,正如您在单例类的示例中了解到的那样,所有全局状态都会让您头疼。传递容器(并使用 ContainerAware)是需要避免的事情。通过将容器传递给您的服务,您使它们依赖于整个服务世界。仅传递您真正需要的协作者会更干净。它也更容易测试。

  • 经过近两年的时间,我可以说:效果非常好。我添加了带有适当依赖注入的 Symfony-DiC。然后我写了一个“门面”Container::get($id) Container::getParam($key)。用它替换了我的代码中所有愚蠢的实例化。Container-Class 用于抛出弃用并将其记录到 Kibana。很久以后我就能够删除那些糟糕的代码:-) 很好。谢谢。 (3认同)