问题三,如果我们定义类构造函数的时候依赖其他的参数怎么办?
# class Container# 复制上面的代码
# testing
class Person{
private $name;
private $isProgrammer;
public function __construct($name,$isProgrammer = true) {
$this->name = $name;
$this->isProgrammer = $isProgrammer;
}
public function me() {
$message = $this->isProgrammer ? ',Ta是一个程序员' :'';
return "姓名: {$this->name} $message";
}
}
$container = new Container();
$container->bind('Person');
$p1 = $container->make('Person',[
'name' => 'lilei',
]);
echo $p1->me();
# 这样看肯定是不行的,会报出错误
接下来继续解决问题
class Container {
private $bindings = [];
private $instances = [];
public function getClosure($concrete) {
# 让闭包带参
return function($parameter = []) use($concrete) {
#将参数传递给具体的类、就算构造函数不需要参数这样写也不会有任何问题
return new $concrete($parameter);
};
}
public function bind($abstract , $concrete=null, $shared = false)
{
if (is_null($concrete)) {
$concrete = $abstract;
}
if (!$concrete instanceof Closure) {
$concrete = $this->getClosure($concrete);
}
$this->bindings[$abstract] = [
'concrete' => $concrete,
'shared' => $shared
];
}
# 在这里添加一个$paramters 参数
public function make($abstract ,array $parameters = []) {
if (!isset($this->bindings[$abstract])) {
return false;
}
if (isset($this->instances[$abstract])) {
return $this->instances[$abstract];
}
# 那么其实在这里处理一下就可以了
# 需不需要参数?到底需不需要参数我们不知道
# 因为$this->bindings[$abstract]['concrete'] 是一个闭包函数
$concrete = $this->bindings[$abstract]['concrete'];
#$concrete($parameters) 相当于使用getClosure中闭包函数;
# $concrete = function() use($concrete1) {
// return new $concrete1;
// };
# 如果想传递一个参数给闭包那么应该修改一下getClosure方法,让闭包方法带参
$object = $concrete($parameters);
if($this->bindings[$abstract]['shared']) {
$this->instances[$abstract] = $object;
}
return $object;
}
}
#testing
class Person{
private $name;
public function __construct($param) {
$this->name = $param['name'] ?? 'unknown';
}
public function getName() {
return $this->name;
}
}
虽然看起来解决了带参问题,但是问题很明显。我们给构造函数传递的参数是一个数组,我们无法做到让每个人写的插件都把构造函数写成这样。透明性并不好。