h3

php--容器

<?php
class A{
    private $b;
    public function __construct(B $b){
        $this->b = $b;
    }
    public function dosomething(){
        $this->b->dosomething();
        echo __METHOD__, '我是a';
    }
}

class B{
    private $c;
    public function __construct(C $c){
        $this->c = $c;
    }
    public function dosomething(){
        $this->c->dosomething();
        echo __METHOD__, '我是b';
    }
}

class C{
    public function dosomething(){
        echo __METHOD__, '我是c';
    }
}

class Container
{
    private $s = array();
    public function __set($k, $c){
        var_dump($k);
        $this->s[$k] = $c;
    }

    public function __get($k){
        var_dump($k);
        return $this->build($this->s[$k]);
    }
    public function build($className){
        // 判断是否是闭包函数
        if ($className instanceof Closure) {
            // 执行闭包函数,返回结果
            return $className($this);
        }

        // 反射
        $reflector = new ReflectionClass($className);

        // 检查类是否可以实例化,排除抽象类和接口
        if (!$reflector->isInstantiable()) {
            throw new Exception('cant isInstantiable this');
        }

        // 获取类的构造函数
        $constructor = $reflector->getConstructor();

        // 判断是否具有构造函数
        if (is_null($constructor)) {
            return new $className;
        }

        // 有构造函数的话,取构造函数的参数,通过reflectionParameter 数组返回参数列表
        $parameters = $constructor->getParameters();

        // 递归解析构造函数的参数
        $dependencies = $this->getDependencies($parameters);

        // 创建一个类的新实例,给出的参数将传递到类的构造函数
        return $reflector->newInstanceArgs($dependencies);
    }

    // 递归的解析构造函数的参数
    public function getDependencies($parameters){
        $dependencies = [];
        foreach ($parameters as $parameter) {
            $dependency = $parameter->getClass();

            if (is_null($dependency)) {
                // 是变量,有默认值值设置默认值
                $dependencies[] = $this->resolveNonClass($parameter);
            } else {
                // 是一个类,递归解析
                $dependencies[] = $this->build($dependency->name);
            }
        }
        return $dependencies;
    }

    // 返回默认值
    public function resolveNonClass($parameter){
        // 有默认值返回默认值
        if ($parameter->isDefaultValueAvailable()) {
            return $parameter->getDefaultValue();
        }

        throw new Exception('i have no idea what to do hear');
    }
}

// 使用容器,自动加载需要的类
$class = new Container();
$class->b = 'B';
$class->a = function ($class){
    return new A($class->b);
};
$model = $class->a;
$model->doSomething();

注:上边的代码是借鉴的网上的资源,侵删,谢谢。理解过程是自己写的,不对的地方请大神批评

/**
* 解释一下上边示例的运行过程
* 1,实例化容器对象
* 2,给属性b进行赋值,触发了__set(),$s['b'] = 'B'
* 3, 给属性a进行赋值,触发了__set(), $s['a'] = function(...)
* 4, 获取属性a的值的时候触发了__get(), 然后调用方法build
* 5, 判断出a的值为一个闭包函数,执行了该闭包函数
* 6,执行过程中实例化a的时候,调用属性b,此时又触发了方法__get(), 调用build方法
* 7,通过判断是否是闭包函数,是否是抽象类或者接口,然后通过反射,知道该类具有构造函数,通过反射得到其构造函数的参数,然后递归的解析构造函数的参数。在解析参数的过程中识别到了参数为一个类,因此递归的调用了build方法,接着经过一系列的判断,反射,解析等,创建了C类的新实例,然后将给出的参数传递到类的构造函数,然后实例化B类,实例化A类,再调用a的doSomething方法,触发b的doSomething,触发c的doSomething方法
*/

posted @ 2018-12-12 14:57  码上平天下  阅读(398)  评论(0编辑  收藏  举报