ech*_*ber 60 php oop inheritance dependency-injection inversion-of-control
快进:
我写这篇文章的目的是为了更好地理解依赖注入和IoC容器,以及之后我可以纠正它中的错误并用它来帮助教我的一些朋友关于它们.
截至目前,我已经尝试阅读各种框架(laravel,fuel,codeigniter,symfony)的文档,我发现框架中有太多不同的方面,我需要感觉舒服使用它,我决定尝试在尝试在框架中使用它们之前,先单独学习每个主要部分.
我花了几个小时搜索各种含义,查看stackoverflow响应,阅读各种文章试图了解什么是IoC以及如何使用它来正确管理依赖关系,我相信我理解它在概念中是什么,但我仍然是灰色的关于如何正确实现它.我认为阅读本文的任何人帮助我的最好方法是给出我目前对IoC容器和依赖注入的理解,然后让那些比我更了解的人指出我的理解不足的地方.
我的理解:
所以在这一点上,我开始尝试使用IoC容器来处理更复杂的场景.到目前为止,为了使用IoC容器,我似乎只限于我想要创建的任何类的has-a关系,它具有它想要在IoC容器中定义的依赖项.如果我想创建一个继承类的类,但只有在以IoC容器中注册的特定方式创建父类时,该怎么办?
例如:我想创建一个mysqli的子类,但是我想在IoC容器中注册这个类,只是实例化我以前在IoC容器中注册的方式构造的父类.在没有重复代码的情况下,我无法想到这样做的方法(因为这是一个学习项目,我试图尽可能保持'纯').这里有一些我想要描述的例子.
以下是我的一些问题:
我知道这是非常漫长的,只是想提前感谢任何花时间阅读它的人,甚至更愿意分享他们的知识.
laf*_*for 123
简单地说(因为它不仅仅局限于OOP世界),依赖性是组件A需要(依赖于)组件B来完成它应该做的事情的情况.该单词还用于描述此场景中的依赖组件.要将其置于OOP/PHP术语中,请考虑以下示例与强制性汽车类比:
class Car {
public function start() {
$engine = new Engine();
$engine->vroom();
}
}
Run Code Online (Sandbox Code Playgroud)
Car 依赖于Engine.Engine是Car的依赖性.这段代码非常糟糕,因为:
Car代码之前,你不知道它在那里Enginewith MockEngine用于测试目的或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);
Run Code Online (Sandbox Code Playgroud)
以上是构造函数注入的示例,其中依赖项(依赖对象)通过类构造函数提供给依赖(使用者).另一种setEngine方法是在Car类中公开一个方法并使用它来注入一个实例Engine.这称为setter注入,主要用于应该在运行时交换的依赖项.
任何不平凡的项目由一堆相互依存的组成部分,并且它会很容易失去的轨道上得到什么地方注射很快.一个依赖注入容器是一个知道如何实例化和配置其他对象的对象,知道他们与项目的其他对象的关系是并执行依赖注入你.这使您可以集中管理所有项目(内部)依赖项,更重要的是,可以更改/模拟其中一个或多个,而无需编辑代码中的一堆位置.
让我们放弃汽车比喻,看看OP试图实现的目标.假设我们有一个Database取决于mysqli对象的对象.假设我们想要使用一个非常原始的依赖变量容器类DIC来公开两个方法:register($name, $callback)注册一种在给定名称下创建对象的方法,并resolve($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'));
});
Run Code Online (Sandbox Code Playgroud)
请注意,我们告诉容器mysqli 从自身获取一个实例来组装一个实例Database.然后,为了获得一个Database自动注入依赖关系的实例,我们只需:
$database = $dic->resolve('database');
Run Code Online (Sandbox Code Playgroud)
这是它的要点.Pimple是一个稍微复杂但仍然相对简单易懂的PHP DI/IoC容器.查看其文档以获取更多示例.
关于OP的代码和问题:
mysqliWrapper课程延伸 mysql或依赖它.IoC从内部进行调用,mysqliWrapper您可以将一个依赖项交换为另一个.您的对象不应该知道或使用容器; 否则它不再是DIC它的服务定位器(反)模式.require在容器中注册它,因为你不知道,如果你打算在所有使用这个类的一个对象之前一个类文件.在一个地方完成所有容器设置.如果您不使用自动装带器,则可以require在容器中注册的匿名功能中使用.其他资源: