2016-01-05 32 views
2

我有一些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); 
} 

但我如何能最好地让我的“单级”,这是仅称为静态内部的容器?

+0

'var_dump($ instance);'并检查你所得到的。 –

+0

这是虚拟代码。我知道我到了那里。 我的问题是在静态方法“getInstance”的上下文中无法使用$ container。我如何从我的全球范围注入它? – psren

+0

'$ instance-> setContainer($ container);'在这里你通过传递'$ container'参数来调用方法'setContainer'问问你自己,在使用之前你在哪里得到它? –

回答

2

某处早在你的启动代码,但容器实例化后,您可以在容器传给你的单例类:

Singleton::setContainer($container); 

这将容器存放在一个静态属性:

final class Singleton 
{ 
    // ... 

    private static $container; 

    public static function setContainer(ContainerInterface $container) 
    { 
     self::$container = $container; 
    } 
} 

但是,正如你在单例课程的例子中学到的那样,所有的全局状态都给你带来了麻烦。传递容器(并使用ContainerAware)是可以避免的。通过将容器传递给你的服务,你使他们依赖于整个服务世界。只有通过你真正需要的合作者才更清洁。测试也容易得多。

+0

我了解最佳做法。但在这一刻,我必须保留遗留类,因为有些客户依赖它们。我无法控制CodeBase,所以我必须保持BC。这有点难以解释,但我将在后面重构并摆脱完整的课程。 – psren

+1

经过近两年的时间,我可以说:这个解决得很好。 我用适当的依赖注入添加了Symfony-DiC。 然后我写了一个“facade”Container :: get($ id)Container :: getParam($ key)。 用我的代码替换了所有愚蠢的实例。 Container-Class用于抛弃弃用并将它们记录到Kibana。方式后来我能够删除低劣的代码:-) 不错。谢谢。 – psren

4

另一种方法是在全球范围内访问容器,当你需要它:

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

当然也有不对的做法各种各样的事情,但只要你正在转换那么它足以让通过。

+2

这是有风险的,因为它也允许其他人从$ _GLOBAL访问容器。在你试图清理的代码库中,你不应该开放新的机会来搞砸。 –

+0

无论全球都在那里。就像Symfony的设计一样。开发人员不要滥用它。 – Cerad

+0

我的问题是,有大量的狗屎...... 我试图让事情的第一个容器使用全局状态使用服务容器。 然后我开始抛弃全球使用的废弃物,并开始将部件重构为适当的DI。 我很喜欢这个方法,而且我几乎完成了重构应用程序的工作。 – psren