上次实现了简单的依赖注入,但是有个问题,像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');