lumen容器模仿
阅读原文时间:2023年07月08日阅读:1

<?php
class Container {

private $bindings = \[\];  
private $instances = \[\];

public function getClosure($concrete) {  
    return function($parameter = \[\]) use($concrete) {

        # 在这里我们找到了判断初始化函数的契机,利用反射我们可以做很多事,包括我们的问题  
        # 1.获得一个$concrete类反射  
        $reflector = new ReflectionClass($concrete);  
        # 2.判断这个类能否被实例化,例如 private function \_\_construct(){}  
        if(!$reflector->isInstantiable()) {  
            throw new Exception("{$concrete} 无法被实例化");  
        }

        # 3.获取构造函数反射方法  
        $constructor = $reflector->getConstructor();

        # 4.获取参数列表  
        $parameters = $constructor->getParameters();

        # 5.遍历参数列表  
        $instancesParams = \[\];  
        foreach ($parameters as $\_parameter) {  
            # 如果已经$parameter中已经设置了对应的参数  
            if(isset($parameter\[$\_parameter->name\])) {  
                $instancesParams\[\] = $parameter\[$\_parameter->name\];  
                continue;  
            }

            # 如果没设置判断一下这个参数是否存在默认值  
            if(!$\_parameter->isDefaultValueAvailable()) {  
                throw new Exception("{$concrete} 无法被实例化,缺少参数{$\_parameter->name}");  
            }

            $instancesParams\[\] = $\_parameter->getDefaultValue();  
        }

        # 这里就需要通过反射来构建对象了  

// return new $concrete($parameter);
return $reflector->newInstanceArgs($instancesParams);
};
}

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  
    \];  
}

public function make($abstract ,array $parameters = \[\]) {  
    if (!isset($this->bindings\[$abstract\])) {  
        return false;  
    }

    if (isset($this->instances\[$abstract\])) {  
        return $this->instances\[$abstract\];  
    }

    # 先获取到具体的类型  
    $concrete = $this->bindings\[$abstract\]\['concrete'\];  
    # 这里需要思考一下  
    # 到目前为止我们的$this->bindings\[$abstract\]\['concrete'\]里存储的都是通过getClosure方法生成的闭包。  
    # 那么直接在这里判断类型肯定行不通,所以我们跳到getClosure里面去看看  
    $object = $concrete($parameters);  
    if($this->bindings\[$abstract\]\['shared'\]) {  
        $this->instances\[$abstract\] = $object;  
    }

    return $object;  
}  

}

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',null,false);
$p1 = $container->make('Person',[
'name' => 'lilei',
'age'=>10
]);

$p2 = $container->make('Person',[
'name' => 'zhangsan',
'age'=>10
]);

echo $p1->me();
echo $p2->me();

var_dump($p1,$p2);
var_dump($p1 === $p2);

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章