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


Pass Dependency Injection Container to static method

我有一些Legacy类。许多类都是使用Factory类实例化的。

还有一个单身班。

将来我想用DIC完全取代它们。目前,要做到这一点,代码库太大了。

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

final class Singleton
{
  private static $singletonCache = array();
  public static function getInstance($namespace, $className)
  {
  }
}

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

$instance = new $className();
if($instance instanceof ContainerAwareInterface)
{
  // TODO: how do we get the container here
  $instance->setContainer($container);
}

但是,我如何才能最好地将容器放在我的"singleton类"中,它只是静态调用的?

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

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

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

在引导代码的早期,但在容器实例化后,您可以将容器传递给您的singleton类:

Singleton::setContainer($container);

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

final class Singleton
{
    // ...
    private static $container;
    public static function setContainer(ContainerInterface $container)
    {
        self::$container = $container;
    }
}

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

这个答案中提供了另一个解决方案,它与这个问题的另一个答案几乎相同,只是使用global关键字而不是$_GLOBAL数组来访问内核对象。

public static function getInstance($namespace, $className)
{
  global $kernel;
  $container = $kernel->getContainer();
}