简单地说(因为它不是仅限于OOP世界的问题),依赖性是组件A需要(依赖于)组件B来做它应该做的东西的情况。该词也用于描述此场景中依赖的组件。为了把这放在OOP / PHP的术语,考虑下面的例子与强制车比喻:
class Car {
public function start() {
$engine = new Engine();
$engine->vroom();
}
}
汽车依靠发动机。引擎是汽车的依赖。这段代码是很糟糕,但是,因为:
>依赖是隐式的;你不知道它在那里,直到你检查车的代码
>类紧密耦合;您不能使用MockEngine替换引擎以进行测试,或者不能使用TurboEngine替换原有的TurboEngine而不修改Car。
>看起来有点傻,一辆汽车能够为自己建一个发动机,不是吗?
依赖注入是一种解决所有这些问题的方法,通过使Car需要Engine显式并明确地提供它:
class Car {
protected $engine;
public function __construct(Engine $engine) {
$this->engine = $engine;
}
public function start() {
$this->engine->vroom();
}
}
$engine = new SuperDuperTurboEnginePlus(); // a subclass of Engine
$car = new Car($engine);
上面是构造函数注入的一个例子,其中依赖(依赖对象)通过类构造函数提供给依赖(消费者)。另一种方法是在Car类中暴露一个setEngine方法,并使用它来注入一个Engine实例。这被称为setter注入,并且主要用于应该在运行时交换的依赖关系。
任何不平凡的项目都包括一堆相互依赖的组件,它很容易失去被注入的地方很快的轨道。依赖注入容器是一个知道如何实例化和配置其他对象的对象,知道它们与项目中的其他对象之间的关系,并为您执行依赖注入。这使您可以集中管理所有项目的(内部)依赖项,更重要的是,可以更改/模拟其中一个或多个项目,而无需编辑代码中的一堆空间。
让我们来看看汽车的类比,看看OP想要实现的例子。假设我们有一个依赖mysqli对象的数据库对象。让我们假设我们想使用一个真正的原始的依赖引用容器类DIC,它暴露了两个方法:register($ name,$ callback)注册一个在给定名称下创建对象的方法,并解析($ name)那个名字。我们的容器设置看起来像这样:
$dic = new DIC();
$dic->register('mysqli', function() {
return new mysqli('somehost','username','password');
});
$dic->register('database', function() use($dic) {
return new Database($dic->resolve('mysqli'));
});
注意,我们告诉我们的容器从自己获取一个mysqli的实例来组装一个Database的实例。然后得到一个数据库实例及其依赖关系自动注入,我们将简单地:
$database = $dic->resolve('database');
这是它的要点。一个稍微更复杂但仍然相对简单和容易掌握PHP DI / IoC容器是Pimple.检查其文档更多的例子。
关于OP的代码和问题:
>不要对你的容器使用静态类或单例(或者对于任何其他事情);检查痘痘。
>确定您是否希望您的mysqliWrapper类扩展mysql或依赖它。
>通过从mysqliWrapper中调用IoC,您将交换一个依赖关系。您的对象不应该意识到或使用容器;否则不是DIC,它的服务定位器(反)模式。
>在注册容器之前不需要类文件,因为你不知道是否要使用该类的对象。在一个地方做所有的容器设置。如果你不使用自动加载器,你可以要求在你注册容器的匿名函数里面。
其他资源: