PHP具有完全的反射API,供应了对类、接口、函数、要领和扩大举行逆向工程的才。经由过程类的反射供应的才我们能够晓得类是怎样被定义的,它有什么属性、什么要领、要领都有哪些参数,类文件的途径是什么等很主要的信息。恰是由于类的反射,许多PHP框架才完成依靠注入自动处理类与类之间的依靠关联,这给我们日常平凡的开辟带来了很大的轻易。
本文主如果解说怎样应用类的反射来完成依靠注入(Dependency Injection),并不会去逐条报告PHP Reflection里的每个API。为了更好地明白,我们经由过程一个例子来看类的反射,以及怎样完成依靠注入。
下面这个类代表了坐标系里的一个点,有两个属性横坐标x和纵坐标y。
/** * Class Point */ class Point { public $x; public $y; /** * Point constructor. * @param int $x horizontal value of point's coordinate * @param int $y vertical value of point's coordinate */ public function __construct($x = 0, $y = 0) { $this->x = $x; $this->y = $y; } }
接下来这个类代表圆形,能够看到在它的组织函数里有一个参数是Point类的,即Circle类是依靠与Point类的。
class Circle { /** * @var int */ public $radius;//半径 /** * @var Point */ public $center;//圆心点 const PI = 3.14; public function __construct(Point $point, $radius = 1) { $this->center = $point; $this->radius = $radius; } //打印圆点的坐标 public function printCenter() { printf('center coordinate is (%d, %d)', $this->center->x, $this->center->y); } //盘算圆形的面积 public function area() { return 3.14 * pow($this->radius, 2); } }
ReflectionClass
下面我们经由过程反射来对Circle这个类举行反向工程。把Circle类的名字通报给reflectionClass来实例化一个ReflectionClass类的对象。
$reflectionClass = new reflectionClass(Circle::class); //返回值以下 object(ReflectionClass)#1 (1) { ["name"]=> string(6) "Circle" }
反射出类的常量
$reflectionClass->getConstants();
返回一个由常量称号和值组成的关联数组
array(1) { ["PI"]=> float(3.14) }
经由过程反射猎取属性
$reflectionClass->getProperties();
返回一个由ReflectionProperty对象组成的数组
array(2) { [0]=> object(ReflectionProperty)#2 (2) { ["name"]=> string(6) "radius" ["class"]=> string(6) "Circle" } [1]=> object(ReflectionProperty)#3 (2) { ["name"]=> string(6) "center" ["class"]=> string(6) "Circle" } }
反射出类中定义的要领
$reflectionClass->getMethods();
返回ReflectionMethod对象组成的数组
array(3) { [0]=> object(ReflectionMethod)#2 (2) { ["name"]=> string(11) "__construct" ["class"]=> string(6) "Circle" } [1]=> object(ReflectionMethod)#3 (2) { ["name"]=> string(11) "printCenter" ["class"]=> string(6) "Circle" } [2]=> object(ReflectionMethod)#4 (2) { ["name"]=> string(4) "area" ["class"]=> string(6) "Circle" } }
我们还能够经由过程getConstructor()来零丁猎取类的组织要领,其返回值为一个ReflectionMethod对象。
$constructor = $reflectionClass->getConstructor();
反射出要领的参数
$parameters = $constructor->getParameters();
其返回值为ReflectionParameter对象组成的数组。
array(2) { [0]=> object(ReflectionParameter)#3 (1) { ["name"]=> string(5) "point" } [1]=> object(ReflectionParameter)#4 (1) { ["name"]=> string(6) "radius" } }
依靠注入
好了接下来我们编写一个名为make的函数,通报类称号给make函数返回类的对象,在make里它会帮我们注入类的依靠,即在本例中帮我们注入Point对象给Circle类的组织要领。
//构建类的对象 function make($className) { $reflectionClass = new ReflectionClass($className); $constructor = $reflectionClass->getConstructor(); $parameters = $constructor->getParameters(); $dependencies = getDependencies($parameters); return $reflectionClass->newInstanceArgs($dependencies); } //依靠剖析 function getDependencies($parameters) { $dependencies = []; foreach($parameters as $parameter) { $dependency = $parameter->getClass(); if (is_null($dependency)) { if($parameter->isDefaultValueAvailable()) { $dependencies[] = $parameter->getDefaultValue(); } else { //不是可选参数的为了简朴直接赋值为字符串0 //针对组织要领的必需参数这个状况 //laravel是经由过程service provider注册closure到IocContainer, //在closure里能够经由过程return new Class($param1, $param2)来返回类的实例 //然后在make时回调这个closure即可剖析出对象 //细致细节我会在另一篇文章内里形貌 $dependencies[] = '0'; } } else { //递归剖析出依靠类的对象 $dependencies[] = make($parameter->getClass()->name); } } return $dependencies; }
定义好make要领后我们经由过程它来帮我们实例化Circle类的对象:
$circle = make('Circle'); $area = $circle->area(); /*var_dump($circle, $area); object(Circle)#6 (2) { ["radius"]=> int(1) ["center"]=> object(Point)#11 (2) { ["x"]=> int(0) ["y"]=> int(0) } } float(3.14)*/
经由过程上面这个实例我简朴形貌了一下怎样应用PHP类的反射来完成依靠注入,Laravel的依靠注入也是经由过程这个思绪来完成的,只不过设想的更邃密精美大批地应用了闭包回调来应对种种庞杂的依靠注入。
引荐教程:PHP视频教程
以上就是php口试怎样完成反射注入的细致内容,更多请关注ki4网别的相干文章!