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


      突然好奇laravel的依赖注入是怎么实现的,翻看了下laravel的源码,发现在laravel在src/Illuminate/Routing/Route.php下的run方法中开始执行控制器方法

        /**
         * Run the route action and return the response.
         *
         * @return mixed
         */
        public function run()
        {
            $this->container = $this->container ?: new Container;
    
            try {
                if ($this->isControllerAction()) {
                    return $this->runController();
                }
    
                return $this->runCallable();
            } catch (HttpResponseException $e) {
                return $e->getResponse();
            }
        }

      追踪runController方法,一直到src/Illuminate/Routing/RouteDependencyResolverTrait.php下,我们可以看到,laravel使用反射机制进行依赖注入

        /**
         * Resolve the object method's type-hinted dependencies.
         *
         * @param  array  $parameters
         * @param  object  $instance
         * @param  string  $method
         * @return array
         */
        protected function resolveClassMethodDependencies(array $parameters, $instance, $method)
        {
            if (! method_exists($instance, $method)) {
                return $parameters;
            }
    
            return $this->resolveMethodDependencies(
                $parameters, new ReflectionMethod($instance, $method)
            );
        }

      通过对laravel源码的查看,网上资料,以及PHP手册的查阅,自己写了个简单的依赖注入实现。

      首先假设存在一个model叫user

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

      然后存在一个控制器叫UserController

    class UserController
    {
    
        /**
         * 获取表名称
         *
         * @param  \User  $user
         *
         * @return void
         */
        public static function getTableName(User $user){
            echo $user->table;
        }
    }

      可以看到我们的getTableName方法中依赖注入了User类的实例,接下来我们需要通过反射来为这个方法注入参数,注入具体实现如下

    class app
    {
        /**
         * @param  mixed   $controller  控制器
         * @param  string  $method      方法
         *
         * @throws \ReflectionException
         * @throws \Exception
         */
        public static function run($controller, string $method){
    
            //判断方法是否存在
            if (! method_exists($controller, $method))
            {
                throw New Exception("Method [$method] is not exist !");
            }
    
            //通过反射获取方法信息
            $reflectionMethod = New ReflectionMethod($controller,$method);
    
            //携带参数执行该方法
            $reflectionMethod->invokeArgs(new $controller,self::getMethodParams($reflectionMethod));
    
        }
    
    
        /**
         * 获取方法的参数并实例化
         * @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;
        }
    }

      最后我们执行方法,打印出User类的table属性,这样我们就通过映射实现了一个简单的依赖注入。

    app::run('UserController','getTableName');

      

      所有实例代码如下
      

    <?php
    
    //model
    class User
    {
        public $table = 'users';
    }
    
    //控制器
    class UserController
    {
    
        /**
         * 获取表名称
         *
         * @param  \User  $user
         *
         * @return void
         */
        public static function getTableName(User $user){
            echo $user->table;
        }
    }
    
    //容器
    class app
    {
        /**
         * @param  mixed   $controller  控制器
         * @param  string  $method      方法
         *
         * @throws \ReflectionException
         * @throws \Exception
         */
        public static function run($controller, string $method){
    
            //判断方法是否存在
            if (! method_exists($controller, $method))
            {
                throw New Exception("Method [$method] is not exist !");
            }
    
            //通过反射获取方法信息
            $reflectionMethod = New ReflectionMethod($controller,$method);
    
            //携带参数执行该方法
            $reflectionMethod->invokeArgs(new $controller,self::getMethodParams($reflectionMethod));
    
        }
    
    
        /**
         * 获取方法的参数并实例化
         * @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');

      

  • 相关阅读:
    MySql(六)单表查询
    MySql(五)
    MySql(四)
    MySql(三)
    MySql(二)
    2016高管必看的五大互联网营销方法
    昨日股市暴跌熔断 赵薇亏3.3亿赔惨了(如何预测今年股市走向)
    何炅加入阿里音乐预示“互联网+”三大发展走向
    《老炮儿》的江湖道义就是互联网创业的规矩?
    世界互联网大会三大看点 传递什么信号?
  • 原文地址:https://www.cnblogs.com/zhouyuanpei/p/15775554.html
Copyright © 2020-2023  润新知