PHP 인터뷰에서 반사 주입을 구현하는 방법

王林
풀어 주다: 2023-02-25 16:42:02
원래의
2900명이 탐색했습니다.

PHP 인터뷰에서 반사 주입을 구현하는 방법

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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿