lumen-ioc容器测试 (5)
问题三,如果我们定义类构造函数的时候依赖其他的参数怎么办?
# 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; } }
虽然看起来解决了带参问题,但是问题很明显。我们给构造函数传递的参数是一个数组,我们无法做到让每个人写的插件都把构造函数写成这样。透明性并不好。