依赖注入的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');
原文地址:https://www.cnblogs.com/zhouyuanpei/p/15797930.html