[PHP] Reflection - Method편


Study/PHP  2019. 9. 26. 09:00

안녕하세요. 명월입니다.


이 글은 PHP의 Reflection - Method편에 관한 글입니다.


이전에 제가 Reflection의 Class에 대해 설명했습니다. Reflection으로 Class를 찾고 인스턴스를 생성을 설명했습니다.

링크 - [PHP] Reflection - Class편


이번에는 Reflection에서 생성된 클래스 안의 메소드를 찾고 동적으로 실행하는 방법에 대한 설명입니다..

<?php
  class EXClass {
    public function test(){
      return "test";
    }
    public function test1(){
      return "test1";
    }
    public function test2(){
      return "test2";
    }
  }
  // 파라미터 param로 값을 받는다.
  $param = @$_GET["param"];
  // Reflection으로 EXClass를 찾는다.
  $r = new ReflectionClass('EXClass'); 
  // 인스턴스를 생성시킨다.
  $obj = $r->newInstance();
  // 파라미터가 없을 경우는 test함수, 1일경우 test1의 함수, 2일경우는 test2의 함수를 가져온다.
  $m = $r->getMethod("test".$param);
  // 함수를 실행한다.
  $data = $m->invoke($obj);
?>
<!DOCTYPE html>
<html>
<head>
<title>title</title>
</head>
<body>
  <?=$data?>
</body>
</html>

위 소스를 보면 파라미터로 부터 값을 받아서 실행하는 함수가 다릅니다. 만약 Reflection이 없었다면 아래와 같이 작성했을 것입니다.

$obj = new EXClass();
$data = "";
$param = @$_GET["param"];
if($param == "1"){
	$data = $obj->test1();
} else if($param == "2"){
	$data = $obj->test2();
} else {
	$data = $obj->test();
}

여기서 나중에 사양에 의해 함수를 계속 추가해야 한다면 if else가 계속 늘어날 것입니다. 여기서는 제가 간략하게 설명했지만, 좀 더 확장적으로 생각하면 웹 호출시에 Query string의 파라미터에 의해 직접 함수를 호출하는 프로그램을 만든다고 가정한다면 아마 엄청 복잡하게 될 것입니다. 그럴 때, 이 Reflection 기능을 사용하면 코드를 줄일 수 있고 좀 더 가독성이 좋은 소스 코드가 될 것입니다.

Reflection의 Method 기능은 동적 호출만 있는 것은 아닙니다. 일반적으로 우리가 클래스에서 함수를 호출할 때 외부에서 접근 가능한 접근자는 public이고 내부에서 접근 가능한 접근자는 private, 파생 클래스에서 접근 가능한 접근자는 protected입니다. Reflection을 이용하면 이런 접근 제한의 룰을 무시하고 함수를 호출을 할 수 있습니다.

<?php
  class EXClass {
    public function test1(){
      return "test";
    }
    private function test2(){
      return "test1";
    }
    protected function test3(){
      return "test2";
    }
  }
  $r = new ReflectionClass('EXClass'); 
  $obj = $r->newInstance();
  // 루프로 test1부터 test3까지 호출해서 $data 배열에 결과 값을 넣는다.
  for($i=1; $i <= 3; $i++){
    $m = $r->getMethod("test".$i);
    // private, protected의 경우에 외부에서 호출이 가능하게 한다.
    $m->setAccessible(true);
    $data[] = $m->invoke($obj);  
  }
?>
<!DOCTYPE html>
<html>
<head>
<title>title</title>
</head>
<body>
  <?=$data[0]?><br />
  <?=$data[1]?><br />
  <?=$data[2]?><br />
</body>
</html>

클래스를 보면 test2와 test3의 함수는 private와 protected로 설정되어 있습니다. 그럼에도 불구하고 클래스 외부에서 호출되어 $data변수에 값이 다 들어갔습니다.

<?php
  class EXClass {
    public function test($data, $data1, $data2){
      return "test";
    }
  }
  $r = new ReflectionClass('EXClass'); 
  $obj = $r->newInstance();
  $m = $r->getMethod("test");
  // test함수의 파라미터 내역 출력
  var_dump($m->getParameters());
?>
<!DOCTYPE html>
<html>
<head>
<title>title</title>
</head>
<body>
</body>
</html>

php의 경우는 클래스의 메소드 오버로드(동일한 메소명에 파라미터의 타입과 갯수로 함수를 구분하는 것)가 없습니다. 그렇기 때문에 딱히 Reflection으로 메소드를 찾을 때, 따로 파라미터의 종류나 갯수는 필요가 없습니다만, Invoke함수를 호출할 때, 파라미터의 갯수가 일치하지 않으면 에러가 발생하기 때문에 파라미터 검증이 필요할 수도 있습니다. php의 경우는 따로 변수 타입이 없기 때문에, 변수 이름과 갯수등으로 검증 처리를 해야 겠네요..

참조 링크 - https://www.php.net/manual/en/class.reflectionmethod.php


여기까지 PHP의 Reflection - method편에 관한 설명이었습니다.


궁금한 점이나 잘못된 점이 있으면 댓글 부탁드립니다.