乱码乱a∨中文字幕,在线免费激情视频,亚洲欧美久久夜夜潮,国产在线网址

  1. <sub id="hjl7n"></sub>

    1. <sub id="hjl7n"></sub>

      <legend id="hjl7n"></legend>

      當前位置:首頁 >  站長 >  編程技術(shù) >  正文

      PHP反射基礎知識回顧

       2020-10-30 13:38  來源: 腳本之家   我來投稿 撤稿糾錯

        阿里云優(yōu)惠券 先領(lǐng)券再下單

      這篇文章主要介紹了PHP 反射的相關(guān)資料,幫助大家回顧和理解PHP的相關(guān)知識,感興趣的朋友可以了解下

      反射是編程語言的高級特性,能在運行時讓代碼有感知代碼的能力。PHP自5起支持反射機制,其是各種OOP框架底層實現(xiàn)的重要支撐。

      反射

      從一個簡單的例子理解反射:人有五官四肢,但鮮有人清楚人體內(nèi)部的經(jīng)脈走向、骨骼構(gòu)造。如果你修仙順利,在丹田深處練出元嬰,那么就通過元嬰透析身體內(nèi)部的構(gòu)造。理解內(nèi)部構(gòu)造后,還可以讓元嬰指引體內(nèi)真氣在經(jīng)脈的流向,早日修成正果。

      如其名,反射是(從鏡子里)照出自身。我們寫代碼,告訴代碼怎么運行,事件發(fā)生在編譯期。代碼運行期間,代碼如何知道自己的結(jié)構(gòu)以及能力呢?反射機制相當于代碼的元嬰,使代碼能夠感知自身結(jié)構(gòu),并可(部分)改變運行行為。

      與運行時類型信息(Runtime Type Informatiion, RTTI)不同,反射重點在運行時檢測、感知、改變自身的結(jié)構(gòu)和行為。反射是元編程(metaprogramming)的重要組成部分。

      PHP反射API

      反射不是語法分析,不操作表達式、代碼語句。反射獲取的是代碼的結(jié)構(gòu),即函數(shù)、類這些構(gòu)件的結(jié)構(gòu)。PHP中的反射API均以Reflection開頭(接口Reflector除外),重點在函數(shù)和類兩種結(jié)構(gòu)。而函數(shù)可以看成類的成員函數(shù)(多一個隱式的this參數(shù))或者靜態(tài)成員函數(shù)(public類型),所以了解反射API可從類信息的ReflectionClass開始。

      ReflectionClass提供了以下獲取類基本信息的接口:

      getProperties:獲取成員變量/屬性,返回一個ReflectionProperty數(shù)組;ReflectionProperty類中有對屬性詳細說明的API:是否默認屬性(isDefault),是否私有屬性(isPrivate)等。同時ReflectionClass還提供獲取特定類別屬性的API:getDefaultProperties,getStaticProperties;

      getConstants:獲取類中定義的常量;

      getMethods:獲取類中定義的方法,返回一個ReflectionMethod數(shù)組;ReflectionMethod將在下文講解;

      getInterfaces:獲取類實現(xiàn)的接口;

      getParentClass:獲取父類的ReflectionClass實例。

      在反射中,類、接口、特性不分家,所以ReflectionClass提供類型判定API:isInterface、isTrait。

      除了以上基本信息,ReflectionClass(包括ReflectionMethod/ReflectionFunction)還提供了一些不可思議的能力:

      getDocComment:獲取類的文檔注釋信息;

      getFilename:獲取類定義的文件;

      getStartLine: 獲取類定義的起始行號;

      getEndLine: 獲取類定義的結(jié)束行號;

      getModifiers:獲取類定義的修飾符,其意義名字可通過Reflection::getModifierNames得到,例如:abstract,final。

      如果說前述的類結(jié)構(gòu)信息可以通過現(xiàn)有的API獲取(method_exits/property_exits等),上面列出的功能基本上只能通過反射API獲?。≒HP文件中定義的類并且知道定義文件,可以利用token_get_all得到相同結(jié)果,但是實現(xiàn)非常復雜)。這些行為發(fā)生在運行期間。由此可見反射API在分析類結(jié)構(gòu)信息功能上的強大。

      除了ReflectionClass,ReflectionMethod和ReflectionFunction是另外反射中另外兩個重要的類。函數(shù)(function)定義在類外部,方法(method)定義在類內(nèi)部,兩者其實同源,在反射API中有共同的父類:ReflectionFunctionAbstract。ReflectionFunctionAbstract有兩者的大部分API,并且基本上是最重要的API。其中最值得關(guān)注的是其參數(shù)信息的API:getParameters。其獲取函數(shù)的參數(shù)信息,返回一個ReflectionParameter數(shù)組。結(jié)合getParameters和ReflectionParameter,函數(shù)(方法)的結(jié)構(gòu)基本上就清晰了。

      API操作

      知道人體構(gòu)造和體內(nèi)真氣分布,你可以引導真氣到手指,練成一陽指、六脈神劍、彈指神通、九陰白骨爪等;也可以讓真氣匯聚,沖破任督二脈,開辟洞天;還可以逆轉(zhuǎn)全身經(jīng)脈,練成*蟆功…內(nèi)省的好處可見一斑。

      反射讓代碼感知自身結(jié)構(gòu),有什么好處呢?反射API提供了三種在運行時對代碼操作的能力:

      設置訪問控制權(quán):setAccessible??色@取私有的方法/屬性。注意:setAccessible只是讓方法/成員變量可以invoke/getValue/setValue,并不代表類定義的訪問存取權(quán)限改變;

      調(diào)用函數(shù)/方法:invoke/invokeArgs。配合獲取函數(shù)參數(shù)的API,可以安全的傳參和調(diào)用函數(shù),call_user_func(_array)的增強版;

      不依賴構(gòu)造函數(shù)生成實例:newInstanceWithoutConstructor。

      以單例來說一下反射API的功能,單例類代碼如下:

      # foo.php
      class Foo {
       private static $id;
       private static $instance;

       private function __construct() {
       ++ self::$id;
       fwrite(STDOUT, "construct, instance id: " . self::$id . "\n");
       }

       public static function getSingleton() {
       if (self::$instance === null) {
       self::$instance = new self();
       }
       return self::$instance;
       }
      }

      在Foo類中,構(gòu)造函數(shù)是私有,獲取實例只能通過getSingleton方法,并且獲取到的是單例。但在反射API加持下,能獲取多個實例:

      $instance1 = Foo::getSingleton();
      var_dump($instance1);

      $class = new ReflectionClass("Foo");
      $constructor = $class->getConstructor();
      if ((ReflectionProperty::IS_PUBLIC & $constructor->getModifiers()) === 0) {
       $constructor->setAccessible(true);
      }
      $instance2 = $class->newInstanceWithoutConstructor();
      $constructor->invoke($instance2);
      var_dump($instance2);

      # 腳本執(zhí)行結(jié)果
      construct, instance id: 1
      object(Foo)#1 (0) {
      }
      construct, instance id: 2
      object(Foo)#4 (0) {
      }

      我們成功的生成了兩個實例,并調(diào)用構(gòu)造函數(shù)完成對象初始化。如果沒有反射API,這幾乎是不可能完成的工作。

      除了這三種操作,反射API幾乎已無在運行時動態(tài)改變代碼的行為。但作為動態(tài)語言,PHP內(nèi)置了將數(shù)據(jù)轉(zhuǎn)換成代碼執(zhí)行的能力(例如create_function/eval、動態(tài)函數(shù)名調(diào)用)。而PHP的好基友JavaScript則可以隨時在運行時改變?nèi)我夂瘮?shù)的行為:

      PHP作為最好的語言,理應能做到在運行時動態(tài)增減/改變函數(shù)定義。這就需要用到另一個PHP核心開發(fā)者“Dmitry Zenovich”打造的大殺器:runkit拓展。這部分內(nèi)容不屬于反射,加之本人了解不深,不再詳述。

      對比

      整理一下反射API和函數(shù)式API在功能上的差異:

      總結(jié)

      本文對PHP中的反射機制做了簡要總結(jié),并與在運行時獲取代碼信息的函數(shù)式API做了對比。即使你token_get_all用得再熟練,preg_match等文本操作用得再順手,反射API仍有其獨到一面,值得了解。如本人之前博文“PHP中的重載”所言,有了反射,function_exits/class_exits、call_user_func這些函數(shù)應該可以退休。但是考慮到兼容、使用便利、運行效率等因素,許多框架仍然依賴這些API。

      感謝閱讀,歡迎指正!

      以上就是PHP反射知識回顧的詳細內(nèi)容,更多關(guān)于PHP 反射的資料請關(guān)注腳本之家其它相關(guān)文章!

      來源:腳本之家

      鏈接:https://www.jb51.net/article/195310.htm

      申請創(chuàng)業(yè)報道,分享創(chuàng)業(yè)好點子。點擊此處,共同探討創(chuàng)業(yè)新機遇!

      相關(guān)標簽
      php教程

      相關(guān)文章

      熱門排行

      信息推薦