• 依赖注入的PHP实现(二)


      上次实现了简单的依赖注入,但是有个问题,像laravel是可以实现构造函数依赖注入,但是上次实现的依赖注入不支持构造函数的依赖注入,所以今天把构造函数的依赖注入一并实现了。

      跟上次一样,假设有一个名为user的model

      

    class User
    {
        public $table = 'users';
    }

     我们还有个名为UserController的控制器,我们需要在UserController的构造方法中依赖注入User,如下图所示

      

    class UserController
    {
        protected $user;
    
         public function __construct(User $user){
            $this->user = $user;
         }
    
        public function getTableName(){
            echo $this->user->table;
        }
    }

      之前我们是直接new了个Usercontroller的实例给invokeArgs

    //携带参数执行该方法
    $reflectionMethod->invokeArgs(new $controller,self::getMethodParams($reflectionMethod));

      那么要实现构造函数的依赖注入,那么我们就需要在实例化UserController时把构造函数的依赖实例化并注入,查询了下php手册,发现了ReflectionClass类下有newInstanceArgs这个方法可以在实化类的时候传入参数,那我们故技重施,先通过反射类获取构造函数的信息,然后实例化参数,再调用newInstanceArgs实例化Usercontroller,这样就完成了构造函数依赖的注入。

        public static function run ($controller, $method)
        {
            if (! method_exists($controller, $method))
            {
                echo "Method [$method] is not exist !";exit;
            }
            
            //通过反射获取类信息
            $reflector = New ReflectionClass($controller);
    
            //获取构造方法信息,实例化参数
            $constructor = $reflector->getConstructor();
            $constructParams = self::getMethodParams($constructor);
    
            //创建一个类的新实例,给出的参数将传递到类的构造函数
            $instance = $reflector->newInstanceArgs($constructParams);
    
            //获取执行方法信息,实例化参数
            $reflectionMethod = New ReflectionMethod($controller,$method);
            $methodParams = self::getMethodParams($reflectionMethod);
    
            //执行反射的方法
            $reflectionMethod->invokeArgs($instance, $methodParams);
        }

       测试代码效果,成功输出了user的table属性

        

        所有示例代码如下

    <?php
    
    class User
    {
        public $table = 'users';
    }
    
    class Article
    {
        public $table = 'articles';
    }
    
    class UserController
    {
        protected $user;
    
         public function __construct(User $user){
            $this->user = $user;
         }
    
        public function getTableName(Article $article){
            echo $this->user->table . PHP_EOL; 
            echo $article->table;
        }
    }
    
    class app
    {
    
        public static function run ($controller, $method)
        {
            if (! method_exists($controller, $method))
            {
                echo "Method [$method] is not exist !";exit;
            }
            
            //通过反射获取类信息
            $reflector = New ReflectionClass($controller);
    
            //获取构造方法信息,实例化参数
            $constructor = $reflector->getConstructor();
            $constructParams = self::getMethodParams($constructor);
    
            //创建一个类的新实例,给出的参数将传递到类的构造函数
            $instance = $reflector->newInstanceArgs($constructParams);
    
            //获取执行方法信息,实例化参数
            $reflectionMethod = New ReflectionMethod($controller,$method);
            $methodParams = self::getMethodParams($reflectionMethod);
    
            //执行反射的方法
            $reflectionMethod->invokeArgs($instance, $methodParams);
        }
    
        /**
         * 获取方法的参数并实例化
         * @param $reflectionMethod
         *
         * @return array
         * @throws \Exception
         */
        public static function getMethodParams($reflectionMethod) : array
        {
            $result = [];
    
            foreach ($reflectionMethod->getParameters() as $key => $param) {
                $class = $param->getClass();
    
                if ($class)
                {
                    $result[] = New $class->name(); 
                }else{
                    throw New Exception('arguments ' . $key . 'is error!');
                }
            }
    
            return $result;
        }
    }
    
    app::run('UserController', 'getTableName');
  • 相关阅读:
    python 面向对象编程的三大特征之一 多态
    python 访问控制
    python 面向对象编程的三大特征之一 继承
    朱兆祺教你如何攻破C语言学习、笔试与机试的难点
    如何画好流程图
    2013年个人计划
    30天敏捷结果(1):总体认识Getting Result敏捷方法
    每天一个linux命令目录
    国嵌C语言学习
    【head first python】1.初识python 人人都爱列表
  • 原文地址:https://www.cnblogs.com/zhouyuanpei/p/15797930.html
Copyright © 2020-2023  润新知