zoukankan      html  css  js  c++  java
  • PHP的Reflection反射机制

    原文地址: http://www.nowamagic.net/php/php_Reflection.php

    PHP5添加了一项新的功能:Reflection。这个功能使得程序员可以

    reverse-engineer[逆向工程] class, interface,function,method and extension[扩展库支持]。

    通过PHP代码,就可以得到某object的所有信息,并且可以和它交互。

    如假设以下Person类:

     1 class Person {
     2     /**
     3      * For the sake of demonstration, we"re setting this private
     4      */
     5     private $_allowDynamicAttributes = false;
     6     
     7     /**
     8      * type=primary_autoincrement
     9      */
    10     protected $id = 0;
    11     
    12     /**
    13      * type=varchar length=255 null
    14      */
    15     protected $name;
    16     
    17     /**
    18      * type=text null
    19      */
    20     protected $biography;
    21     public function getId() {
    22         return $this->id;
    23     }
    24     public function setId($v) {
    25         $this->id = $v;
    26     }
    27     public function getName() {
    28         return $this->name;
    29     }
    30     public function setName($v) {
    31         $this->name = $v;
    32     }
    33     public function getBiography() {
    34         return $this->biography;
    35     }
    36     public function setBiography($v) {
    37         $this->biography = $v;
    38     }
    39 }

    通过ReflectionClass,我们可以得到Person类的以下信息:

    • 常量 Contants
    • 属性 Property Names
    • 方法 Method Names
    • 静态属性 Static Properties
    • 命名空间 Namespace
    • Person类是否为final或者abstract

    只要把类名"Person"传递给ReflectionClass就可以了:

    1 $class = new ReflectionClass('Person');

    * 获取属性(Properties):

    1 $properties = $class->getProperties();
    2 foreach($properties as $property) {
    3     echo $property->getName()."
    ";
    4 }
    5 // 输出:
    6 // _allowDynamicAttributes
    7 // id
    8 // name
    9 // biography

    默认情况下,ReflectionClass会获取到所有的属性,private 和 protected的也可以。如果只想获取到private属性,就要额外传个参数:

    1 $private_properties = $class->getProperties(ReflectionProperty::IS_PRIVATE);

    可用参数列表:

    • ReflectionProperty::IS_STATIC
    • ReflectionProperty::IS_PUBLIC
    • ReflectionProperty::IS_PROTECTED
    • ReflectionProperty::IS_PRIVATE

    如果要同时获取public 和private 属性,就这样写:ReflectionProperty::IS_PUBLIC | ReflectionProperty::IS_PRIVATE

    通过$property->getName()可以得到属性名,通过getDocComment可以得到写给property的注释。

     1 foreach($properties as $property) {
     2     if($property->isProtected()) {
     3         $docblock = $property->getDocComment();
     4         preg_match('/ type=([a-z_]*) /', $property->getDocComment(), $matches);
     5         echo $matches[1]."
    ";
     6     }
     7 }
     8 // Output:
     9 // primary_autoincrement
    10 // varchar
    11 // text

    有点不可思议了吧。竟然连注释都可以取到。

    * 获取方法(methods):通过getMethods() 来获取到类的所有methods。返回的是ReflectionMethod对象的数组。

    不再演示。

    赋一个利用反射加载类实例的工具类写法:

    <?php
    /**
     * Desc: 反射加载类
     * Class: ClassLoader
     * Package: AppLib
     * User: zb
     * Date: 2019/5/22 15:21
     */
    
    namespace AppLib;
    
    class ClassLoader
    {
        private static $obj = [];
    
        /**
         * 上传类map
         */
        private static function uploadClassMap ()
        {
            $map = [
                'image' => 'AppLibUploadImage',//key为传递参数key
                'video' => 'AppLibUploadVideo',
            ];
            return $map;
        }
    
        /**
         * model类map
         */
        private static function modelClassMap ()
        {
            $map = [
                'video' => 'AppModelVideo',
            ];
            return $map;
        }
    
        /**
         * aliyun类map
         */
        private static function aliyunClassMap ()
        {
            $map = [
                'vod' => 'AppLibAliyunAliyunVod',
            ];
            return $map;
        }
    
        /**
         * cache类map
         */
        private static function cacheClassMap ()
        {
            $map = [
                'video' => 'AppLibCacheVideo',
            ];
            return $map;
        }
    
        /**
         * 类实例map指南
         * @param string $guideKey 指南key
         * @param string $classKey classKey
         * @return array|bool
         */
        private static function guideClassMap (string $guideKey, string $classKey)
        {
            $guideKey = strtolower($guideKey);
            $guideMap = [
                'upload' => self::uploadClassMap(),
                'model' => self::modelClassMap(),
                'aliyun' => self::aliyunClassMap(),
                'cache' => self::cacheClassMap(),
            ];
            return isset($guideMap[$guideKey][$classKey]) ? $guideMap[$guideKey][$classKey] : array();
        }
    
        /**
         * @param string $guideKey guideKey
         * @param string $classKey classKey键
         * @param array $params 构造函数参数
         * @param bool $instance 是否需要实例化
         * @return object|string 返回obj或字符串
         * @throws ReflectionException
         */
        public static function initClass (string $guideKey, string $classKey, $params = [], $instance = true)
        {
            if (!$params && isset(self::$obj[$guideKey . '-' . $classKey]) && is_object(self::$obj[$guideKey . '-' . $classKey])) {
                return self::$obj[$guideKey . '-' . $classKey];
            } else {
                unset(self::$obj[$guideKey . '-' . $classKey]);
            }
    
            if (!self::guideClassMap($guideKey, $classKey)) {
                throw new ReflectionException('加载类不存在');
            }
            $class = self::guideClassMap($guideKey, $classKey);
            try {
                $obj = $instance ? (new ReflectionClass($class))->newInstanceArgs($params) : $class;
                if (!$params) {
                    self::$obj[$guideKey . '-' . $classKey] = $obj;
                }
                return $obj;
            } catch (ReflectionException $e) {
                throw new ReflectionException('类加载失败');
            }
        }
    
    }
  • 相关阅读:
    进程 线程 协程之间的区别与联系
    http协议基础 5.关于http请求响应报文的总结
    http协议基础 4. http请求报文格式
    http协议基础 3.URI URL 与URN之间的联系与区别。
    python面试题----持续更新中
    python之禅
    Django 2.0 报错解决方案----持续更新中
    4
    3
    2
  • 原文地址:https://www.cnblogs.com/deverz/p/6138373.html
Copyright © 2011-2022 走看看