什么是依赖注入?
先看一段伪代码
class DB{
private $db;//这里可能是pdo 可能是别的,仅仅为了演示
public function __construct($connInfo)
{
//.....做些pdo或者mysqli等初始化工作
}
public function queryForRows($sql){
return ['id'=>101,"username"=>"qidong"];
}
}
class MyUser{
private $mydb;
public function __construct($dsn)
{ //$dsn当做可以连接的字符串。
$this->mydb=new DB($dsn);
//主动实例化
}
public function getAllUsers():array{
//是业务方法
return $this->mydb->queryForRows("select * from users");
}
}
$user=new MyUser("mysql:host=localhost;");
var_dump($user->getAllUsers());
上面缺点非常明显:
MyUser简称为A。 Db简称为B
两个类过于耦合。我们把MyUser和数据库两个概念 混淆在了一起 ,变成了一个。当数据库密码或者其他信息更换,我们要从MyUser的构造函数传参数,去修改Db类。调用方式属于先调用A—->B。正向关系。
修改后代码:
class MyUser{
private $mydb;
public function __construct(DB $db)
{ //强制要求类型是DB类
$this->mydb=$db;
}
public function getAllUsers():array{
//是业务方法
return $this->mydb->queryForRows("select * from users");
}
}
$db=new DB("mysql:host=localhost;");
$user=new MyUser($db);
var_dump($user->getAllUsers());
依赖注入Dependency Injection (DI)
:个人理解。调用A类的时候。A类需要的依赖参数,不是A类的内部生成。而是以外部注入的方式传入。
控制反转Inversion of Control (IoC)
:和正向调用相反,我使用A必须在之前调用B。就叫控制反转。执行顺序B—>A。
IOC容器的概念。就是加了一个存储对象的容器而已。
IOC容器的简单实现
class Container
{
private static $container=[];
public static function set(string $name,callable $func)
{
self::$container[$name]=$func;
}
/**
*
* @param string $name
* @return null
*/
public static function get(string $name)
{
if(isset(self::$container[$name])){
//下面代码可以理解立即执行闭包函数
return (self::$container[$name])();
}
return null;
}
}
Container::set('MyDb',function(){
return new MyDb('xx');
});
Container::set('MyUser',function(){
return new MyUser(Container::get('MyDb'));
});
$MyUser=Container::get('MyUser');
var_dump($MyUser->getAllUsers());