如何在PHP中正确注入依赖项

4

我遇到了一些关于依赖注入的问题,希望能够澄清一下。首先要提到的是我实现的一个依赖注入容器(DIC),它能够使用ReflectionClass通过构造函数注册和解析依赖项。

$container = new DiC;
$container->register('session', 'CSession');
$container->register('response', 'CResponse');
$container->register('model', 'CSomeModel');
$container->register('view', 'CSomeView');
$container->register('controller', 'CSomeController');

一个依赖的控制器:
class CSomeController extends CController
{
  public function __construct(CSomeModel $model, CSomeView $view)
  {
    // assign arguments here
  }
}

现在控制器可以通过DIC来实例化:

$controller = $container->resolve('controller');

我喜欢这种方法,因为它是自动化和描述性的,但是CController类依赖于特定的CSomeModel、CSomeView类,这是不好的。MVC三元组应该独立实例化,例如我不能将COtherView传递给CSomeController。

我的第二个想法是注入DIC:

class CSomeController extends CController
{
  public function __construct(DiC $dic)
  {
    // resolve dependencies through $dic
  }
}

这个方法使得DiC对象成为全局变量,许多人认为这不是实施依赖注入的正确方式。是否有第三种方式能够消除两种方法的弱点呢?

你介意发布你的 DiC 类吗? - Matt Kantor
1
你应该看一下Laravel4是如何处理这个问题的,特别是"将接口绑定到实现"这一部分。 你可以在Github找到相关源代码。 - vFragosop
Symfony2使用非常稳定的DI组件,该组件基于Java Spring...这与您正在做的类似..但更进一步..http://symfony.com/doc/2.0/components/dependency_injection/introduction.html - Dinesh
2个回答

1

我认为这两种方法都很相关。如果您想在第一种方法中更加灵活,可以将构造函数更改为具有父类依赖项。然后,从该父类继承的每个对象都可以进行注入。例如:

class CSomeModel extends AbstractCModel {}
class CSomeOtherModel extends AbstractCModel {}

public function __construct(AbstractCModel $model, AbstractCView $view) {}

第二种方法适用于需要访问工厂的情况。例如,如果您需要访问多个相同对象的实例。

1
IoC类通过使用PHP反射来解决依赖关系。通过注入抽象类,我失去了自动化... - user1517081
一个接口比抽象类更好。 - EmeraldD.

1
如果你正在寻找“自动连接”,请转向接口并实现你的具体模型/视图等类。这样你就可以使用反射来配对双方。
在容器级别上明确指定依赖关系的机制也是有意义的。

这方面有教程吗? - Simon Josef Kok

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接