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" }
Reflect 클래스 상수
$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" } }
ReflectionMethod 객체의 배열을 반환
$reflectionClass->getMethods();
getConstructor()를 통해 클래스의 생성자 메소드를 별도로 얻을 수도 있고, 그 반환값은 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" } }
메서드의 매개변수를 반영합니다
$constructor = $reflectionClass->getConstructor();
반환값은 ReflectionParameter 개체로 구성된 배열입니다.
$parameters = $constructor->getParameters();
종속성 주입
다음으로 make라는 함수를 작성하고, 클래스 이름을 make 함수에 전달하고 클래스의 객체를 반환합니다. make에서는 클래스의 종속성을 주입하는 데 도움이 됩니다. , 이 예에서는 Circle 클래스의 생성자에 Point 개체를 삽입하는 데 도움이 됩니다.
array(2) { [0]=> object(ReflectionParameter)#3 (1) { ["name"]=> string(5) "point" } [1]=> object(ReflectionParameter)#4 (1) { ["name"]=> string(6) "radius" } }
make 메소드를 정의한 후 이를 사용하여 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; }
위의 예를 통해 PHP 클래스의 리플렉션을 사용하여 종속성 주입을 구현하는 방법을 간략하게 설명했습니다. , Laravel 종속성 주입도 이 아이디어를 통해 구현되지만 디자인이 더 정교하고 클로저 콜백을 사용하여 다양하고 복잡한 종속성 주입을 처리합니다.
추천 튜토리얼: PHP 비디오 튜토리얼
위 내용은 PHP 인터뷰에서 반사 주입을 구현하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!