lumen容器模仿

<?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);

  

原文地址:https://www.cnblogs.com/brady-wang/p/13734143.html