개발 꿀팁/PHP

php 반사 API를 이용한 클래스 정보 획득

Jammie 2022. 6. 27. 17:40
반응형

PHP는 완전한 반사 API를 가지고 있어 클래스, 인터페이스, 함수, 방법 및 확장에 대해 역방향 엔지니어링을 할 수 있다.API를 반사하여 함수, 클래스 및 메소드에서 문서 주석을 추출하는 메소드를 제공한다.본고에서는 PHP 반사 API를 이용한 클래스 정보 획득 방법을 소개하고, 완전한 데모 코드를 제공한다.
PHP 반사 API 문서 주소http://php.net/manual/zh/class.reflectionclass.php
ReflectionClass를 사용하여 클래스의 속성, 인터페이스, 방법 등의 정보 획득
1.클래스 기본정보 취득

$ref = new ReflectionClass($classname);
echo $ref->getName();
echo $ref->getFileName();

2.클래스 속성 정보 가져오기

$ref = new ReflectionClass($classname);
$properties = $ref->getProperties();
foreach($properties as $property){
    echo $property->getName();
}

3.클래스 메소드 정보 취득

$ref = new ReflectionClass($classname);
$methods = $ref->getMethods();
foreach($methods as $method){
    echo $method->getName();
}

4.클래스 인터페이스 정보 취득

$ref = new ReflectionClass($classname);
$interfaces = $ref->getInterfaces();
foreach($interfaces as $interface){
    echo $interface->getName();
}

데모 코드
읽기 위한 IUser 인터페이스 만들기, User 클래스, Vip 클래스
User.class.php

<?php
/** 사용자 인터페이스 */
interface IUser{

    // 신규가입자
    public function add($data);

    // 사용자 데이터 읽기
    public function get($id);

}

/** 사용자 클래스 */
class User implements IUser{

    /** 
      * 사용자 데이터
      */
    protected $user = array();

    /**
     * 신규가입자
     * @param  Array $data 사용자 데이터
     * @return Int
     */
    public function add($data){
        $this->user[] = $data;
        $keys = array_keys($this->user);
        return end($keys);
    }

    /**
     * 사용자 데이터 읽기
     * @param  Int    $id 用户id
     * @return Array
     */
    public function get($id){
        if(isset($this->user[$id])){
            return $this->user[$id];
        }else{
            return array();
        }
    }

}

/** VIP사용자 클래스 */
class Vip extends User{

    /**
     * vip 사용자 데이터 읽기
     * @param  Int    $id 사용자id
     * @return Array
     */
    public function getvip($id){
        $data = $this->get($id);
        if($data){
            return $this->format($data);
        }
        return $data;
    }

    /**
     * 데이터를 수정하다
     * @param  Array $data 사용자 데이터
     * @return Array
     */
    private function format($data){
        $data['is_vip'] = 1;
        return $data;
    }

}

?>

Ref 클래스 만들기PHP 반사 클래스 불러오기클래스 정보
Ref.class.php

<?php
/**
 * 클래스 정보를 얻기 위해 PHP 반사 클래스 호출
 * Date:    2017-05-24
 * Author:  fdipzone
 * Ver:     1.0
 *
 * Func
 * public static setClass       반사 클래스 설정
 * public static getBase        클래스 기본 정보 읽기
 * public static getInterfaces  읽기 클래스 인터페이스
 * public static getProperties  클래스 속성 읽기
 * public static getMethods     클래스 읽기 방법
 */
class Ref{

    private static $refclass = null;

    // 반사 클래스 설정
    public static function setClass($classname){
        self::$refclass = new ReflectionClass($classname);
    }

    // 클래스 기본 정보 읽기
    public static function getBase(){
        echo '<strong>BASE INFO</strong>'.PHP_EOL;
        echo 'class name: '.self::$refclass->getName().PHP_EOL;
        echo 'class path: '.dirname(self::$refclass->getFileName()).PHP_EOL;
        echo 'class filename: '.basename(self::$refclass->getFileName()).PHP_EOL.PHP_EOL;
    }

    // 읽기 클래스 인터페이스
    public static function getInterfaces(){
        echo '<strong>INTERFACES INFO</strong>'.PHP_EOL;
        $interfaces = self::$refclass->getInterfaces();
        if($interfaces){
            foreach($interfaces as $interface){
                echo 'interface name: '.$interface->getName().PHP_EOL;
            }
        }
    }

    // 클래스 속성 읽기
    public static function getProperties(){
        echo '<strong>PROPERTIES INFO</strong>'.PHP_EOL;
        $properties = self::$refclass->getProperties();
        if($properties){
            foreach($properties as $property){
                echo 'property name: '.$property->getName().PHP_EOL;
                echo 'property modifier: '.self::getModifier($property).PHP_EOL;
                echo 'property comments: '.self::formatComment($property->getDocComment()).PHP_EOL.PHP_EOL;
            }
        }
    }

    // 클래스 읽기 방법
    public static function getMethods(){
        echo '<strong>METHODS INFO</strong>'.PHP_EOL;
        $methods = self::$refclass->getMethods();
        if($methods){
            foreach($methods as $method){
                echo 'method name: '.$method->getName().PHP_EOL;
                echo 'method modifier: '.self::getModifier($method).PHP_EOL;
                echo 'method params num: '.$method->getNumberOfParameters().PHP_EOL;
                $params = $method->getParameters();
                if($params){
                    foreach($params as $param){
                        echo 'param name:'.$param->getName().PHP_EOL;
                    }
                }
                echo 'method comments: '.self::formatComment($method->getDocComment()).PHP_EOL.PHP_EOL;
            }
        }
    }

    // 수정자 가져오기
    private static function getModifier($o){
        // public
        if($o->isPublic()){
            return 'public';
        }

        // protected
        if($o->isProtected()){
            return 'protected';
        }

        // private
        if($o->isPrivate()){
            return 'private';
        }

        return '';
    }

    // 주석 내용을 서식 설정하다
    private static function formatComment($comment){
        $doc = explode(PHP_EOL, $comment);
        return isset($doc[1])? trim(str_replace('*','',$doc[1])) : '';
    }

}
?>

데모:

<?php
require 'Ref.class.php';
require 'User.class.php';

echo '<pre>';
Ref::setClass('Vip');
Ref::getBase();
Ref::getProperties();
Ref::getMethods();
Ref::getInterfaces();
echo '</pre>';
?>

출력:

BASE INFO
class name: Vip
class path: /home/fdipzone/ref
class filename: User.class.php

PROPERTIES INFO
property name: user
property modifier: protected
property comments: 사용자 데이터

METHODS INFO
method name: getvip
method modifier: public
method params num: 1
param name:id
method comments: vip 사용자 데이터 읽기

method name: format
method modifier: private
method params num: 1
param name:data
method comments: 데이터를 수정하다

method name: add
method modifier: public
method params num: 1
param name:data
method comments: 신규 가입자다.

method name: get
method modifier: public
method params num: 1
param name:id
method comments: 사용자 데이터 읽기

INTERFACES INFO
interface name: IUser
반응형