<?php 

class People
{
    public $dog = null;

    public function __construct()
    {
        $this->dog = new Dog();
    }

    public function putDog(){
        return $this->dog->dogCall();
    }

}



class Dog{
    public function dogCall(){
        return 'go to home....';
    }
}


class Container
{
	/**
	* 容器绑定,用来装提供的实例或者 提供实例的回调函数
	* @var array
	*/
	public $building = [];

	/**
	 * 注册一个绑定到容器
	 */
	public function bind($abstract, $concrete = null, $shared = false)
	{
	    if(is_null($concrete)){
	        $concrete = $abstract;
	    }

	    if(!$concrete instanceOf Closure){
	        $concrete = $this->getClosure($abstract, $concrete);
	        
	    }

	    $this->building[$abstract] =  compact("concrete", "shared");

	    print_r($this->building);
	    // $res = ($this->building)['Dog']['concrete'];
	    // print_r($res);die;
	    // var_dump($res instanceof Closure);die;

	}

	//注册一个共享的绑定 单例
	public function singleton($abstract, $concrete, $shared = true){
	    $this->bind($abstract, $concrete, $shared);
	}




	/**
	 * 默认生成实例的回调闭包
	 *
	 * @param $abstract
	 * @param $concrete
	 * @return Closure
	 */
	public function getClosure($abstract, $concrete)
	{
	    return function($c) use($abstract, $concrete){

	        $method = ($abstract == $concrete)? 'build' : 'make';

	        print_r($method.PHP_EOL);

	        return $c->$method($concrete);
	    };
	}





	/**
	 * 生成实例 
	 */
	public function make($abstract)
	{
	    $concrete = $this->getConcrete($abstract);

	    $data = $this->isBuildable($concrete, $abstract);

	    // print_r($concrete);die;

	    if( $data ){

	        $object = $this->build($concrete);

	    }else{
	        $object = $this->make($concrete);
	    }



	    return $object;
	}





	/**
	 * 获取绑定的回调函数
	 */
	public function getConcrete($abstract)
	{
	    // if(! isset($this->building[$abstract])  ){
	    //     return $abstract;
	    // }

	    if( is_object($abstract)  ){
	        return $abstract;
	    }


	    return $this->building[$abstract]['concrete'];
	}

	/**
	 * 判断 是否 可以创建服务实体
	 */
	public function isBuildable($concrete, $abstract)
	{
	    return $concrete === $abstract || $concrete instanceof Closure;
	}




	/**
	 * 根据实例具体名称实例具体对象
	 */
	public function build($concrete)
	{
	    if($concrete instanceof Closure){

	        return $concrete($this);
	    }

	    
	    //创建反射对象
	    $reflector = new \ReflectionClass($concrete);


	    print_r($reflector);

	    if( ! $reflector->isInstantiable()){
	        //抛出异常
	        throw new \Exception('error.');
	    }

	    $constructor = $reflector->getConstructor();

	    print_r($constructor);
	    if(is_null($constructor)){
	        return new $concrete;
	    }

	    $dependencies = $constructor->getParameters();

	    print_r($dependencies);


	    $instance = $this->getDependencies($dependencies);

	    print_r( $reflector->newInstanceArgs($instance) );

	    return $reflector->newInstanceArgs($instance);

	}


	//通过反射解决参数依赖
	public function getDependencies(array $dependencies)
	{
	    $results = [];
	    foreach( $dependencies as $dependency ){
	        $results[] = is_null($dependency->getClass())
	            ?$this->resolvedNonClass($dependency)
	            :$this->resolvedClass($dependency);
	    }

	    return $results;
	}

	//解决一个没有类型提示依赖
	public function resolvedNonClass(ReflectionParameter $parameter)
	{
	    if($parameter->isDefaultValueAvailable()){
	        return $parameter->getDefaultValue();
	    }
	    throw new \Exception('error_one.');

	}

	//通过容器解决依赖
	public function resolvedClass(ReflectionParameter $parameter)
	{
	    return $this->make($parameter->getClass()->name);

	}

}

$app = new Container();


$app->bind('Dog','Dog');
$app->bind('People', 'People');
$people = $app->make('People');
echo $people->putDog();



?>

 

posted on 2018-04-20 10:50  阳光小白  阅读(705)  评论(0编辑  收藏  举报