PHP反射メカニズムの紹介

5838 ワード

Php Reflection APIはPHP 5ならではの新機能で、クラス、メソッド、属性、パラメータなどの詳細情報を書き出したり抽出したりするためのものです.
よく使われるのは2つだけで、ReflectionClassとReflectionObject、前者はクラス、後者はオブジェクト、後者は前者を継承するクラスです.次に、対応するreflectionオブジェクトを返すプロパティまたはメソッドもあります.
PHP反射機構、クラス、インタフェース、関数、方法と拡張に対して逆工程を行う能力.
クラス、インタフェース、関数、メソッドの内部構造、メソッドと関数のパラメータ、およびクラスの属性とメソッドを分析します.
よく使用されるクラス:
  • ReflectionClass解析クラス
  • ReflectionPropertyクラスの属性に関する情報
  • ReflectionMethodクラスメソッドに関する情報
  • ReflectionParameter関数またはメソッドパラメータに関する情報
  • を取り出す.
  • ReflectionFunction関数に関する情報
  • サンプルクラス
    class Student
    {
        public $id;
        
        public $name;
    
        const MAX_AGE = 200;
    
        public static $likes = [];
    
        public function __construct($id, $name = 'li')
        {
            $this->id = $id;
            $this->name = $name;
        }
    
        public function study()
        {
            echo 'learning...';
        }
    
        private function _foo()
        {
            echo 'foo';
        }
    
        protected function bar($to, $from = 'zh')
        {
            echo 'bar';
        }
    }
    

    ReflectionClass
    //ReflectionClass
    $ref = new ReflectionClass('student');
    
    //         
    if($ref->isInstantiable()){
        echo "    ";
    }
    
    //      ,   ReflectionMethod  ,    null
    $constructor = $ref->getConstructor();
    
    //      
    if ($ref->hasProperty('id')) {
        $attr = $ref->getProperty('id');
    }
    
    //      
    $attributes = $ref->getProperties();
    foreach ($attributes as $row){
        echo $row->getName()."
    "; } // , $static = $ref->getStaticProperties(); // if ($ref->hasConstant('MAX_AGE')) { $const = $ref->getConstant('MAX_AGE'); } // $constants = $ref->getConstants(); // if ($ref->hasMethod('bar')) { $method = $ref->getMethod('bar'); } // $methods = $ref->getMethods();

    ReflectionProperty
    if ($ref->hasProperty('name')) {
      $attr = $ref->getProperty('name');
      //    
      echo $attr->getName();
      //        ,          
      var_dump($attr->isDefault());
      //        
      $attr->isPrivate();
      $attr->isPublic();
      $attr->isProtected();
      //         
      $attr->isStatic();
    }
    

    ReflectionMethod & ReflectionParameter
    $method = $ref->getMethod('bar');
    //      
    //isAbstruct()
    //isConstructor()
    //isDestructor()
    //isFinal()
    //isPrivate()
    //isPublic()
    //isProtected()
    //isStatic()
    
    //      
    $parameters = $method->getParameters();
    foreach ($parameters as $row) {
        echo $row->getName();
        echo $row->getClass();
        
        //        
        if ($row->isDefaultValueAvailable()) {
            echo $row->getDefaultValue();
        }
      
        //      
        if ($row->hasType()) {
            echo $row->getType();
        }
    }
    

    ReflectionFunction & ReflectionParameter
    $fun = new ReflectionFunction('demo');
    echo $fun->getName();
    $parameters = $fun->getParameters();
    foreach ($parameters as $row) {
        //     $row   ReflectionParameter   
        echo $row->getName();
        echo $row->getClass();
    
        //           
        if ($row->isDefaultValueAvailable()) {
            echo $row->getDefaultValue();
        }
    
        //       
        if ($row->hasType()) {
            echo $row->getType();
        }
    }
    

    総合例
    反射を使用したクラスのインスタンス化
    //student.php
    class Student
    {
        public $id;
        
        public $name;
    
        public function __construct($id, $name)
        {
            $this->id = $id;
            $this->name = $name;
        }
    
        public function study()
        {
            echo 'learning.....';
        }
    
    }
    

    一般的にクラスをインスタンス化するときは直接newが可能であるが,我々は今この方法を用いずに反射を用いて実現している.
    //index.php
    require 'student.php';
    function make($class, $vars = [])
    {
        $ref = new ReflectionClass($class);
      
        if ($ref->isInstantiable()) {
            $constructor = $ref->getConstructor();
            if (is_null($constructor)) {
                return new $class;
            }
          
            //        
            $params = $constructor->getParameters();
            $resolveParams = [];
            foreach ($params as $key => $param) {
                $name = $param->getName();
                if (isset($vars[$name])) {
                    //          ,        
                    $resolveParams[] = $vars[$name];
                } else {
                    //        ,        ,       ,          
                    $default = $param->isDefaultValueAvailable() ? $param->isDefaultValueAvailable() : null;
                    if (is_null($default)) {
                        if ($param->getClass()) {
                            $resolveParams[] = make($value->getClass()->name, $vars);
                        } else {
                            throw new Exception("{$name}          ");
                        }
                    } else {
                         $resolveParams[] = $default;
                    }
                }
            }
            //       
            return $ref->newInstanceArgs($resolveParams);
        } else {
            throw new Exception("  {$class}    ");
        }
    }
    

    ケース1
    try {
        $stu = make('Student', ['id' => 1, 'name'=>'li']);
        print_r($stu);
        $stu->study();
    } catch(Exception $e) {
        echo $e->getMessage();
    }
    

    状況2
    try {
        $stu = make('Student', ['id' => 1, 'name'=>'li', 'study'=> new Study]);
        print_r($stu);
        $stu->study();
    } catch(Exception $e) {
        echo $e->getMessage();
    }
    

    この場合,クラスのコンストラクション関数パラメータを解析する際に,パラメータが伝達されなければ,makeメソッドを再帰的に呼び出してStudyクラスを処理し,クラスが存在すればインスタンス化する.PHPの反射はとても使いやすい機能で、ここでは簡単に説明するしかありません.詳しく紹介し、使い方は公式マニュアルを参照してください.