> 백엔드 개발 > PHP 튜토리얼 > PHP Reflection의 실제 적용 사례 공유

PHP Reflection의 실제 적용 사례 공유

小云云
풀어 주다: 2023-03-21 21:28:01
원래의
1194명이 탐색했습니다.


이 기사에서는 주로 PHP 리플렉션의 실제 적용 사례를 공유합니다. 리플렉션 클래스, 인터페이스, 함수 및 메서드의 내부 구조, 메서드 및 함수의 매개 변수, 속성 및 메서드 분석을 기반으로 문서를 자동으로 생성할 수 있습니다. 수업.

<?phpclass Student{
    const NORMAL = 1;    const FORBIDDEN = 2;    /**
     * 用户ID
     * @var 类型
     */
    public $id;    /**
     * 获取id
     * @return int
     */
    public function getId()
    {
        return $this->id;
    }    public function setId($id = 1)
    {
        $this->id = $id;
    }
}$ref = new ReflectionClass(&#39;Student&#39;);$doc = $ref->getDocComment();echo $ref->getName() . &#39;:&#39; . getComment($ref) , "<br/>";echo "属性列表:<br/>";
printf("%-15s%-10s%-40s<br/>", &#39;Name&#39;, &#39;Access&#39;, &#39;Comment&#39;);$attr = $ref->getProperties();foreach ($attr as $row) {
    printf("%-15s%-10s%-40s<br/>", $row->getName(), getAccess($row), getComment($row));
}echo "常量列表:<br/>";
printf("%-15s%-10s<br/>", &#39;Name&#39;, &#39;Value&#39;);$const = $ref->getConstants();foreach ($const as $key => $val) {
    printf("%-15s%-10s<br/>", $key, $val);
}echo "<br/><br/>";echo "方法列表<br/>";
printf("%-15s%-10s%-30s%-40s<br/>", &#39;Name&#39;, &#39;Access&#39;, &#39;Params&#39;, &#39;Comment&#39;);$methods = $ref->getMethods();foreach ($methods as $row) {
    printf("%-15s%-10s%-30s%-40s<br/>", $row->getName(), getAccess($row), getParams($row), getComment($row));
}// 获取权限function getAccess($method){
    if ($method->isPublic()) {        return &#39;Public&#39;;
    }    if ($method->isProtected()) {        return &#39;Protected&#39;;
    }    if ($method->isPrivate()) {        return &#39;Private&#39;;
    }
}// 获取方法参数信息function getParams($method){
    $str = &#39;&#39;;    $parameters = $method->getParameters();    foreach ($parameters as $row) {        $str .= $row->getName() . &#39;,&#39;;        if ($row->isDefaultValueAvailable()) {            $str .= "Default: {$row->getDefaultValue()}";
        }
    }    return $str ? $str : &#39;&#39;;
}// 获取注释function getComment($var){
    $comment = $var->getDocComment();    // 简单的获取了第一行的信息,这里可以自行扩展
    preg_match(&#39;/\* (.*) *?/&#39;, $comment, $res);    return isset($res[1]) ? $res[1] : &#39;&#39;;
}
로그인 후 복사

출력 결과:

Student:
属性列表:
Name Access Comment 
id Public 用户ID 
常量列表:
Name Value 
NORMAL 1 FORBIDDEN 2 方法列表
Name Access Params Comment 
getId Public 获取id 
setId Public id,Default: 1
로그인 후 복사

2. MVC 아키텍처 구현

이제 많은 프레임워크에서 라우팅 정보를 기반으로 컨트롤러($controller) 및 메서드($method)의 이름을 찾은 다음 리플렉션을 사용하여 자동을 구현합니다. 전화.

$class = new ReflectionClass(ucfirst($controller) . &#39;Controller&#39;);$controller = $class->newInstance();if ($class->hasMethod($method)) {    $method = $class->getMethod($method);    $method->invokeArgs($controller, $arguments);
} else {
    throw new Exception("{$controller} controller method {$method} not exists!");
}
로그인 후 복사

3. 단위 테스트 구현

일반적으로 함수와 클래스가 예상대로 결과를 반환할 수 있는지 테스트합니다. 리플렉션을 사용하여 간단하고 일반적인 클래스 테스트 사례를 구현할 수 있습니다.

<?phpclass Calc{
    public function plus($a, $b)
    {
        return $a + $b;
    }    public function minus($a, $b)
    {
        return $a - $b;
    }
}function testEqual($method, $assert, $data){
    $arr = explode(&#39;@&#39;, $method);    $class = $arr[0];    $method = $arr[1];    $ref = new ReflectionClass($class);    if ($ref->hasMethod($method)) {        $method = $ref->getMethod($method);        $res = $method->invokeArgs(new $class, $data);        if($res === $assert){            echo "测试结果正确";
        };
    }
}
testEqual(&#39;Calc@plus&#39;, 3, [1, 2]);echo  "<br/>";
testEqual(&#39;Calc@minus&#39;, -1, [1, 2]);
로그인 후 복사

이것은 클래스의 테스트 방법이며, 리플렉션을 사용하여 함수의 테스트 방법을 구현할 수도 있습니다.

<?phpfunction title($title, $name){
    return sprintf("%s. %s\r\n", $title, $name);
}$function = new ReflectionFunction(&#39;title&#39;);echo $function->invokeArgs(array(&#39;Dr&#39;, &#39;Phil&#39;));?>
로그인 후 복사

이것은 제가 간단히 작성한 테스트 사례입니다. PHPUnit 단위 테스트 프레임워크는 Reflection의 기능에 크게 의존합니다.

4. DI 컨테이너와 협력하여 종속성 해결

Laravel과 같은 많은 프레임워크는 Reflection을 사용하여 종속성 주입 문제를 해결합니다. 자세한 내용은 Laravel 소스 코드를 참조하세요.
아래 코드는 DI 컨테이너를 구현하여 Reflection이 종속성 주입 문제를 어떻게 해결하는지 보여줍니다.

<?phpclass DI{
    protected static $data = [];    public function __set($k, $v)
    {
        self::$data[$k] = $v;
    }    public function __get($k)
    {
        return $this->bulid(self::$data[$k]);
    }    // 获取实例
    public function bulid($className)
    {
        // 如果是匿名函数,直接执行,并返回结果
        if ($className instanceof Closure) {            return $className($this);
        }        // 已经是实例化对象的话,直接返回
        if(is_object($className)) {            return $className;
        }        // 如果是类的话,使用反射加载
        $ref = new ReflectionClass($className);        // 监测类是否可实例化
        if (!$ref->isInstantiable()) {            throw new Exception(&#39;class&#39; . $className . &#39; not find&#39;);
        }        // 获取构造函数
        $construtor = $ref->getConstructor();        // 无构造函数,直接实例化返回
        if (is_null($construtor)) {            return new $className;
        }        // 获取构造函数参数
        $params = $construtor->getParameters();        // 解析构造函数
        $dependencies = $this->getDependecies($params);        // 创建新实例
        return $ref->newInstanceArgs($dependencies);
    }    // 分析参数,如果参数中出现依赖类,递归实例化
    public function getDependecies($params)
    {
        $data = [];        foreach($params as $param)
        {            $tmp = $param->getClass();            if (is_null($tmp)) {                $data[] = $this->setDefault($param);
            } else {                $data[] = $this->bulid($tmp->name);
            }
        }        return $data;
    }    // 设置默认值
    public function setDefault($param)
    {
        if ($param->isDefaultValueAvailable()) {            return $param->getDefaultValue();
        }        throw new Exception(&#39;no default value!&#39;);
    }
}class Demo{
    public function __construct(Calc $calc)
    {
        echo $calc->plus(1, 2);
    }
}class Calc{
    public function plus($a, $b)
    {
        return $a + $b;
    }    public function minus($a, $b)
    {
        return $a - $b;
    }
}$di = new DI();$di->calc = &#39;Calc&#39;;  
$di->demo = &#39;Demo&#39;;$di->demo;//输出结果为3
로그인 후 복사

관련 권장 사항:

MySQL 데이터베이스 명령의 실제 적용 예

위 내용은 PHP Reflection의 실제 적용 사례 공유의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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