• 深入 Laravel 内核之 PHP 反射机制和依赖注入


    结论:

    • PHP中提供了反射类来解析类的结构;
    • 通过反射类可以获取到类的构造函数及其参数和依赖;
    • 给构造函数的参数递归设置默认值后,即可使用这些带默认值的参数通过 newInstanceArgs 实例化出类对象;
    • 在实例化的过程中,依赖的类也会被实例化,从而实现了依赖注入。

    PHP中反射类的常用方法:

    // 通过类名 Circle 实例化反射类
    $reflectionClass = new reflectionClass(Circle::class);
    // 获取类常量
    $reflectionClass->getConstants();
    // 获取类属性
    $reflectionClass->getProperties();
    // 获取类方法
    $reflectionClass->getMethods();
    // 获取类的构造函数
    $constructor = $reflectionClass->getConstructor();
    // 获取方法的参数
    $parameters = $constructor->getParameters();
    // 通过参数默认值数组实例化类创建对象
    $class = $reflectionClass->newInstanceArgs($dependencies);
    

    创建两个具有依赖关系的类:

    class Point
    {
        public $x;
        public $y;
    
        public function __construct($x = 0, $y = 0)
        {
            $this->x = $x;
            $this->y = $y;
        }
    }
    
    class Circle
    {
        // 圆的半径
        public $radius;
    
        // 圆心位置
        public $center;
    
        const PI = 3.14;
    
        public function __construct(Point $point, $radius = 1)
        {
            $this->center = $point;
            $this->radius = $radius;
        }
    
        // 打印圆心位置的坐标
        public function printCenter()
        {
            printf('圆心的位置是:(%d, %d)', $this->center->x, $this->center->y);
        }
    
        //计算圆形的面积
        public function area()
        {
            return 3.14 * pow($this->radius, 2);
        }
    }
    

    创建两个方法:

    make 方法负责解析类和构建类的对象;

    getDependencies 负责依赖解析并初始化参数默认值;

    //构建类的对象
    function make($className)
    {
        try {
            $reflectionClass = new ReflectionClass($className);
            $constructor = $reflectionClass->getConstructor();
            $parameters  = $constructor->getParameters();
            $dependencies = getDependencies($parameters);
    
            // 用指定的参数创建一个新的类实例
            return $reflectionClass->newInstanceArgs($dependencies);
        } catch (ReflectionException $e) {
            throw new Exception("{$className} not found.");
        }
    }
    
    //依赖解析并初始化参数默认值
    function getDependencies($parameters)
    {
        $dependencies = [];
        // Circle 类的参数为 point 和 radius
        // Point 类的参数为 x 和 y
        foreach($parameters as $parameter) {
            $dependency = $parameter->getClass();
            // 如果参数不是类
            if (is_null($dependency)) {
                // 可选参数,有默认值
                if($parameter->isDefaultValueAvailable()) {
                    $dependencies[] = $parameter->getDefaultValue();
                }
                // 必传参数暂时先给一个默认值
                else {
                    $dependencies[] = '0';
                }
            }
            // 如果参数是类
            else {
                // 递归进行依赖解析
                $dependencies[] = make($parameter->getClass()->name);
            }
        }
    
        return $dependencies;
    }
    

    测试:

    // 实例化对象
    $circle = make('Circle');
    // 调用对象的方法
    $area = $circle->area();
    var_dump($circle, $area);
    

    过程说明:

    make('Circle')
    	getDependencies(Point, int)
    		make('Point')
    			getDependencies(int, int)
    			new Point(int, int);
    		return Point;
    	new Circle(Point, int);
    return Circle;
    
  • 相关阅读:
    docker 的端口映射
    Python OpenCV实现图像模板匹配详解
    async和await用法(Task)
    C#,哈夫曼编码(Huffman Code)压缩(Compress )与解压缩(Decompress)算法与源代码
    python opencv轮廓检测
    Docker 创建镜像、修改、上传镜像
    C# .NET4.0 自定义文件并实现文件与应用程序关联
    How to Assign a Custom Icon to a File Type
    【服务器数据恢复】服务器误删除KVM虚拟机的数据恢复案例
    【服务器数据恢复】OceanStor存储中NAS卷数据丢失的数据恢复案例
  • 原文地址:https://www.cnblogs.com/danhuang/p/13164345.html
Copyright © 2020-2023  润新知