我的理解:
因此,在这一点上,我开始尝试将IoC容器用于更复杂的场景。到目前为止,为了使用IoC容器,似乎我要创建的几乎所有要在IoC容器中定义依赖项的类都具有has- a关系。如果我想创建一个继承类的类怎么办,但仅当父类已以特定方式创建且已在IoC容器中注册时,该怎么办。
因此,例如:我想创建mysqli的子类,但是我想在IoC容器中注册该类,以便仅以以前以我在IoC容器中注册的方式构造的父类实例化。我想不出一种无需复制代码的方法(并且由于这是一个学习项目,我试图将其保持为“纯”)。这是我要描述的更多示例。
所以这是我的一些问题:
简而言之(因为这不仅仅限于OOP世界), 依赖 就是组件A需要(依赖)组件B来完成应做的工作的情况。该词还用于描述这种情况下的依赖组件。为了用OOP / PHP术语来表示,请考虑以下示例,与强制性汽车类比类似:
class Car { public function start() { $engine = new Engine(); $engine->vroom(); } }
Car 依赖 于Engine。Engine是Car的 依赖 。但是这段代码非常糟糕,因为:
Car
Engine
MockEngine
TurboEngine
依赖注入 是一种方法,它通过使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);
上面是 构造函数注入 的示例,其中通过类构造函数将依赖项(被依赖对象)提供给依赖项(消费者)。另一种setEngine方法是在Car类中公开一个方法,并使用该方法注入的实例Engine。这称为“ setter注入” ,主要用于应该在运行时交换的依赖项。
setEngine
任何不平凡的项目都由一堆相互依赖的组件组成,并且很容易很快就就无法确定注入了什么。一个 依赖注入容器 是一个知道如何实例化和配置其他对象的对象,知道他们与项目的其他对象的关系是并执行依赖注入你。这使您可以集中管理所有项目的(相互)依赖关系,更重要的是,可以更改/模拟一个或多个依赖关系,而不必在代码中编辑很多地方。
让我们抛开汽车类比,以OP试图实现的示例为例。假设我们有一个Database取决于mysqli对象的对象。假设我们要使用一个真正原始的依赖项指示符容器类DIC,该类公开两种方法:register($name, $callback)以给定名称注册创建对象的方法,并resolve($name)从该名称获取对象。我们的容器设置如下所示:
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')); });
请注意,我们告诉容器mysqli 从其自身 获取一个实例来组装的实例Database。然后,要获得一个Database实例,它的依赖项会自动注入,我们将简单地:
$database = $dic->resolve('database');
这就是要旨。Pimple是一个稍微复杂但仍相对简单易懂的PHP DI / IoC容器。查看其文档以获取更多示例。
关于OP的代码和问题:
mysqliWrapper
mysql
IoC
require