lumen-ioc容器测试 (5)

lumen-ioc容器测试 (1)

lumen-ioc容器测试 (2)

lumen-ioc容器测试 (3)

lumen-ioc容器测试 (4)

lumen-ioc容器测试 (5)

lumen-ioc容器测试 (6)

问题三,如果我们定义类构造函数的时候依赖其他的参数怎么办?

# 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;
    }
}

  

虽然看起来解决了带参问题,但是问题很明显。我们给构造函数传递的参数是一个数组,我们无法做到让每个人写的插件都把构造函数写成这样。透明性并不好。

posted @ 2020-09-26 10:15  brady-wang  阅读(153)  评论(0编辑  收藏  举报