IoC
ioC 容器,也可以称为服务容器,这个是laravel框架的核心思想,就是说,把东西整合在一个容器中,需要什么就取什么的意思,一个容器,一定要有两个方法,一个是取,一个是存。
这一个就是ioc容器,简单的代码介绍
<?php
class IoC
{
protected static $registry = [];
public static function bind($name, callable $resolver) //传入类名和类对象实例
{
static::$registry[$name] = $resolver;
}
public static function make($name) //静态工厂方法
{
if (isset(static::$registry[$name])) {
$resolver = static::$registry[$name];
return $resolver(); //实例化
}
throw new Exception('Alias does not exist in the IoC registry.');// 容器中没有你想要的对象
}
}
class a
{
public function xx()
{
echo 123;
}
}
IoC::bind('a', function () {
return new a();
});
$a = IoC::make('a');
$a->xx();
php反射
ReflectionClass() 也就是这个类,这个类,他里面封装类很多方法,通过这里面的方法,你可以反射出 另一个类的参数,构造方法,形参,受保护的变量等等,甚至连注释都能反射获取到
依赖注入
所谓依赖,就是a class 依赖 b class 所谓注入,就是把 b class 放到a class 中,然后又把 b class 这个对象 存储在a class 中的一个受保护变量中,这就是依赖注入
看看下面这段代码就是依赖注入
<?php
class a
{
protected $info;
public function __construct(b $b)// 依赖b class
{
$this->info = $b;
}
public function a()
{
return $this->info->b();
}
}
class b
{
public function __construct()
{
}
public function b()
{
return 'class b funciton b';
}
}
$b = new b();
$a = new a($b);
$c = $a->a();
var_dump($c);
ioc容器+php反射 实现依赖注入
<?php
// ioc-di容器 控制反转 依赖注入
// laravel 就是用了ioc这个思想,就是一个类方法,他需要依赖另外一个,是从ioc容器中拿的,而不是直接new的
// 容器就是存储了很多东西,需要的时候就用他的,不需要的时候就不用他
// 不需要在a类中直接newb类,而是让ioc容器将b给a,这就叫做控制反转,将程序内部转移到外部去管理
class peopel {
public function hahah() {
echo 2;
}
}
class phone
{
public $obj;
public $p;
public function __construct(usb $obj, peopel $p)
{
$this->obj = $obj;//注意这里主动去new了需要的对象
$this->p = $p;
}
public function act()
{
$this->obj->dosth();
$this->p->hahah();
}
}
class usb
{
public function dosth()
{
echo 1;
}
}
class container
{
public $objs = [];//存储资源
/***
* 负责存储资源的方法
* @param $class
* @param $closure_obj
*/
public function bind($class, $closure_obj)
{
if (!$closure_obj instanceof Closure) {// $closure_obj instanceof Closure 是不是一个闭包
// 如果不是闭包的话就要把他变成闭包
$this->objs[$class] = function () use ($closure_obj) {
return $this->ref($closure_obj);
};
} else {
// 是闭包的话就把他存储起来
$this->objs[$class] = $closure_obj;
}
}
/***
* 获取存储的资源
* @param $class
* @return mixed
*/
public function make($class)
{
if (isset($this->objs[$class])) {// 当前是不是存在存储资源里面
$new = $this->objs[$class];// 在的话就返回
} else {
/**
下面这步,最终是这样的:
$container->bind('usb', function () {
return new usb;
});
*/
$new = function () use ($class) {
return $this->ref($class);// 如果不在绑定关系里面的话,就要反射一下,而且要是一个闭包
};
}
return $new();
}
/***
* 返回一个实例化的对象,这里用到php反射 也就是这个 ReflectionClass
* @param $class
* @param array $params
* @return mixed|object|null
* @throws ReflectionException
*/
public function ref($class, $params = [])
{
// ReflectionClass 这个是php的反射api
$ref = new ReflectionClass($class);
if ($ref->isInstantiable()) {// isInstantiable检查类是否可实例化
$constructor = $ref->getConstructor();// 获取里面的构造方法 getConstructor
if (!is_null($constructor)) {
$pars = $constructor->getParameters();// 获取里面的参数getParameters,获取构造函数的依赖(形参),返回一组ReflectionParameter对象组成的数组表示每一个参数
if (empty($pars)) {//如果不依赖于任何的类,就直接实例化当前的就行了
return new $class;
} else {// 如果这个形参是存在的,就去获取形参的实例化对象
foreach ($pars as $par) {//如果形参有多个
$dependencyClass = $par->getClass();// 获得类型提示类。就比如这种 function(Par $par) 获取到的就是Par 这个是类的名称
if (is_null($dependencyClass)) {
$dependencies[] = NULL;
} else {
// 类存在创建类实例,make去获取已经存储好的实例,$dependencies这个就是已经实例化后的对象了
$dependencies[] = $this->make($par->getClass()->name);
}
}
return $ref->newInstanceArgs($dependencies);//newInstanceArgs从给出的参数创建一个新的类实例
}
} else {//如果没有构造方法就返回这个对象
return new $class;
}
}
return null;
}
}
$container = new container;
//$container->bind('usb', function () {
// return new usb;
//});
$container->bind('phone', 'phone');
$phone = $container->make('phone');
$phone->act();