之前看了好多框架,laravel,thinkphp,yii等等。基本上都使用了容器。对于我而言,虽然看懂了laravel是怎么写的,但是如果自己不去尝试一下,始终觉得不会这个东西。下面的代码是我实现的一个简单的容器,很多地方处理并不是很好,但是应该已经足够了。<?phpclass Container{ //$binds 这个变量保存,是名字=>实例的映射 private $binds = []; public static $instance = null; /** * 单例 / public static function getInstance(){ if(static::$instance == null){ static::$instance = new static(); return static::$instance ; } return static::$instance; } /* * 一开始是受到laravel的影响,所以写了一个bind函数, * 看完laravel的容器实现,印象之中,$concrete和$abstract来回变换。 * 下面的代码有点像thinkphp的里面的实现,好理解一点 / public static function bind($name,$class = null){ if($class instanceof Closure){ static::getInstance()->binds[$name] = $class; }else if(is_object($class)){ static::getInstance()->binds[$name] = $class; }else{ //在这里开始make一个数组,laravel好像是make和build分开的。 static::getInstance()->make($name); } } /* * 核心是make方法了 / public static function get($name){ return static::getInstance()->make($name); } /* * 核心make方法 */ public function make($name){ try{ //根据类名去查找$this->binds实例是否已经存在,如果存在就直接返回 if(array_key_exists($name,$this->binds)){ return $this->binds[$name]; } //根据类名得到它的反射类 $reflectClass = new ReflectionClass($name); //利用反射类 $constructor = $reflectClass->getConstructor(); //如果没有构造器的话,就直接去实例化它 $params = []; if(!is_null($constructor)){ //获取构造器中的方法 $constructorParams = $constructor->getParameters(); // var_dump($constructorParams); //保存构造器的参数 foreach($constructorParams as $constructorParam){ //这个地方主要是判断参数是否是类,如果是就递归的构造它,不是就简单的添加到$this->params中 if(!is_null($constructorParam->getType())){ $params[] =$this->make($constructorParam->name,$constructorParam->name); }else{ $params[] = $constructorParam->name; } } } //在这个地方构造实例 $class = $reflectClass->newInstanceArgs($params); //绑定 $this->binds[$name] = $class; return $class; }catch(ReflectionException $e){ echo $e->getMessage(); } } private function __construct(){} private function __clone(){}}?>下面是我的测试文件了,<?phprequire “./Container.php”;class TestFather{ private $name = “TestFather”; public function __construct(){ }}class Test extends TestFather{ private $name = “Test”; // public function __construct(DI $di, DI2 $di2,$name){ // } public function __construct(DI $di,$name,$param_2 =[]){ } public function sayName(){ echo $this->name; } public function sayDI2Name(DI2 $di2){ //如果这么写的,di2方法会先于前面的字符串打印出来 // echo “form Test say di2 name: “.$di2->sayName(); echo “form Test say di2 name: “; echo $di2->sayName(); }}class DI{ private $name = “DI”; public function __construct(DI2 $di2){} public function sayName(){ echo $this->name; } }class DI2{ private $name = “DI2”; public function __construct(){} public function sayName(){ echo $this->name; } }class DI3{ private $name = “DI3”; public function __construct(){} public function sayName(){ echo $this->name; } }class DI4{ private $name = “DI4”; public function __construct(){} public function sayName(){ echo $this->name; } }//要不要无所谓了// Container::bind(’test’,‘Test’); $test = Container::get(’test’);$test->sayName();echo “\n”;$test->sayDI2Name(new DI2());echo “\n”;$di = Container::get(‘di’);$di->sayName();echo “\n”;$di2 = Container::get(‘di2’);$di2->sayName();echo “\n”;$di3 = new DI3();Container::get(‘di3’,$di3)->sayName();echo “\n”;$di4 = function(){ return new DI4();};Container::get(‘di4’,$di4)->sayName();echo “\n”;?>最后的结果如下