日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

PHP反射基礎知識回顧

瀏覽:127日期:2022-09-09 08:31:53

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

反射

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

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

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

PHP反射API

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

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

getProperties:獲取成員變量/屬性,返回一個ReflectionProperty數組;ReflectionProperty類中有對屬性詳細說明的API:是否默認屬性(isDefault),是否私有屬性(isPrivate)等。同時ReflectionClass還提供獲取特定類別屬性的API:getDefaultProperties,getStaticProperties; getConstants:獲取類中定義的常量; getMethods:獲取類中定義的方法,返回一個ReflectionMethod數組;ReflectionMethod將在下文講解; getInterfaces:獲取類實現的接口; getParentClass:獲取父類的ReflectionClass實例。

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

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

getDocComment:獲取類的文檔注釋信息; getFilename:獲取類定義的文件; getStartLine: 獲取類定義的起始行號; getEndLine: 獲取類定義的結束行號; getModifiers:獲取類定義的修飾符,其意義名字可通過Reflection::getModifierNames得到,例如:abstract,final。

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

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

API操作

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

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

設置訪問控制權:setAccessible。可獲取私有的方法/屬性。注意:setAccessible只是讓方法/成員變量可以invoke/getValue/setValue,并不代表類定義的訪問存取權限改變; 調用函數/方法:invoke/invokeArgs。配合獲取函數參數的API,可以安全的傳參和調用函數,call_user_func(_array)的增強版; 不依賴構造函數生成實例:newInstanceWithoutConstructor。

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

# foo.phpclass 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類中,構造函數是私有,獲取實例只能通過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);# 腳本執行結果construct, instance id: 1object(Foo)#1 (0) {}construct, instance id: 2object(Foo)#4 (0) {}

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

除了這三種操作,反射API幾乎已無在運行時動態改變代碼的行為。但作為動態語言,PHP內置了將數據轉換成代碼執行的能力(例如create_function/eval、動態函數名調用)。而PHP的好基友JavaScript則可以隨時在運行時改變任意函數的行為:

PHP反射基礎知識回顧

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

對比

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

功能 函數式API 反射API 函數是否存在 function_exists ReflectionFunction 類是否存在 class_exits ReflectionClass 方法是否存在 method_exits ReflectionMethod 變量/屬性是否存在 property_exits ReflectionProperty 獲取類變量 get_class_vars ReflectionClass::getProperties 獲取類方法 get_class_methods ReflectionClass::getMethods 獲取類常量 — ReflectionClass::RegetReflectionConstant(s) 獲取函數/方法參數信息 — ReflectionFunction/Method::getParameters 獲取函數/方法返回值 — ReflectionFunction/Method::getReturnType 類使用的特性 class_uses ReflectionClass::getTraits 獲取父類 class_parents ReflectionClass::getParentClass 獲取類實現的接口 class_implements ReflectionClass::getInterfaceNames 獲取類所在名字空間 __NAMESPACE__ ReflectionClass::getNamespaceName 函數調用 call_user_func(_array) ReflectionMethod(Function)::invoke(Args) 獲取類名 __CLASS__/::class ReflectionClass::getName 獲取函數名 __METHOD__/__FUNCTION__ ReflectionFunction/Method::getName 獲取類/常量/變量/方法修飾符 — ReflectionClass/Constant/Property/Method::getModifiers 獲取所在文件 __FILE__ ReflectionClass/Constant/Function/Method::getFileName 獲取所在行(范圍) — ReflectionClass/Function/Method::getStartLine/getEndLine 獲取文檔 — ReflectionClass/Function/Method::getDocComment extension_loaded ReflectionZendExtension 拓展 get_loaded_extensions ReflectionExtension get_extension_funcs

從上表可以看出反射API較函數式API能提供更全面的信息。還需要注意到__FILE__這類魔術常量是編譯期的工作,不是運行時的能力。

同時給出RTTI的函數式API和反射API在功能上的差異:

功能 函數式API 反射API 類型判斷 is_int/is_bool/is_array等 — 獲取對象的類名 get_class ReflectionObject::getName 獲取對象父類 get_parent_class ReflectionObject::getParentClass 類型/繼承檢測 instanceof/is_a/is_subclass_of ReflectionObject::isInstance/isSubclassOf 生成器 — ReflectionGenerator

總結

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

感謝閱讀,歡迎指正!

以上就是PHP反射知識回顧的詳細內容,更多關于PHP 反射的資料請關注好吧啦網其它相關文章!

標簽: PHP
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
国产精品亚洲人成在99www | 亚洲国产一区二区在线观看| 国产成人a视频高清在线观看| 欧美日韩一区二区国产| 日韩av一区二| 日本中文字幕一区二区视频| 在线国产日韩| 日本成人中文字幕| 日韩欧美2区| 国产精品一区二区三区美女 | 午夜亚洲一区| 日本欧洲一区二区| 久久亚洲欧美| 日韩精品成人在线观看| 欧美日韩一区二区三区在线电影| 国产精品22p| 国产精品成久久久久| 欧美黄色网页| 黄色成人91| 亚洲精品大全| 国产精品一区高清| 麻豆精品在线| 欧美日韩在线播放视频| 乱人伦精品视频在线观看| 91亚洲无吗| 国产成人精品免费视| 国产精品av一区二区| 蜜臀久久99精品久久久久宅男| 日本v片在线高清不卡在线观看| 国产福利资源一区| 五月激情久久| 在线观看视频免费一区二区三区| 国产精品毛片久久久| 水蜜桃久久夜色精品一区| 国产精品呻吟| 国产精品magnet| 日韩电影免费在线观看| 天堂av在线一区| 国产精品第一| 激情综合网站| 国产精品综合| 伊人精品一区| 日韩av网站免费在线| 福利一区在线| 亚洲日本欧美| 国产精品毛片久久| 亚洲精一区二区三区| 国产白浆在线免费观看| 一区二区精品| 日本不卡免费高清视频在线| 美女精品在线观看| 国产精品一区毛片| 婷婷成人在线| 国产精品久久久久久久久久白浆 | 91久久亚洲| 久久不卡日韩美女| 国产综合欧美| 国产日韩一区二区三免费高清| 福利视频一区| 日韩一区精品| 久久久天天操| 国产精品激情电影| 老牛国产精品一区的观看方式| 国内精品美女在线观看| 在线精品亚洲| 成人精品天堂一区二区三区| 18国产精品| 国产女优一区| 波多视频一区| 欧美天堂一区| 日韩中文字幕视频网| 国产精品中文字幕亚洲欧美| 欧美日韩中文一区二区| 国产情侣久久| 亚洲中午字幕| 成人看片网站| 国产高清精品二区| 国产亚洲在线| 日韩一区电影| 国产乱码精品一区二区三区四区 | 性欧美xxxx免费岛国不卡电影| 国产精品视频3p| 亚洲免费观看| sm捆绑调教国产免费网站在线观看| 亚洲精品免费观看| 久久亚洲专区| 成人三级高清视频在线看| 69精品国产久热在线观看| 亚洲一区二区三区免费在线观看| 亚洲午夜天堂| 精品入口麻豆88视频| 日韩毛片网站| 亚洲中字黄色| 蜜桃成人av| 日韩精品欧美| 97精品视频在线看| 久久不见久久见免费视频7| 亚洲色图综合| 欧美成人久久| 久久久国产精品一区二区中文| 综合欧美亚洲| 欧美69视频| 久久久久久黄| 免费看av不卡| 精品国产精品久久一区免费式 | 国产精品v一区二区三区| 亚洲免费成人av在线| 久久亚洲电影| 国产精品女主播一区二区三区| 亚洲成av人片一区二区密柚| 国产精品黄色| 国产精品mm| 国产精品久久久久久久久久妞妞| 婷婷视频一区二区三区| 美女网站久久| 久久最新视频| 免费看日韩精品| 亚洲自拍另类| 免费不卡在线视频| 亚洲欧美不卡| 在线综合亚洲| 久久成人精品| 美日韩精品视频| 亚洲人妖在线| 日韩精品免费视频人成| 亚洲乱码一区| 欧美日韩一区二区国产| 国产精品亚洲综合久久| 久久不卡国产精品一区二区| 麻豆一区二区三| 麻豆精品久久久| 国产精品1区在线| 欧美国产中文高清| 国产精品久久乐| 久久超级碰碰| 国产一区二区三区四区二区| 亚洲黄色免费看| 久久久久国产一区二区| 欧美日韩黑人| 在线亚洲免费| 亚洲一区日本| 亚洲永久精品唐人导航网址| 婷婷精品在线| 国产精品久久久亚洲一区| 国产中文字幕一区二区三区| 欧美成a人国产精品高清乱码在线观看片在线观看久 | 91九色综合| 国产精品v日韩精品v欧美精品网站 | 亚洲精品国产精品粉嫩| 青青国产精品| 精品视频亚洲| 在线精品一区二区| 日韩av一二三| 日韩精品1区2区3区| 欧美日韩亚洲三区| 国产999精品在线观看| 久久久久99| 亚洲丝袜美腿一区| 麻豆精品一区二区综合av| 色婷婷狠狠五月综合天色拍| 久久亚洲国产精品一区二区| 国产日韩一区二区三区在线| 天堂√8在线中文| 亚洲欧美日韩视频二区| 国产精品日韩精品中文字幕| 久草免费在线视频| 99视频精品免费观看| 日韩高清不卡一区| 九九九精品视频| 999国产精品999久久久久久| 亚洲一区有码| 国产一区二区三区久久 | 精品一区二区三区视频在线播放| 欧洲精品一区二区三区| 日本欧洲一区二区| 免费在线日韩av| 欧美 日韩 国产一区二区在线视频| 亚洲a级精品| av高清不卡| 日韩欧美久久| 中文字幕在线官网| 亚洲久久一区| 日韩欧美精品| 日韩和欧美的一区| 91精品精品| 美腿丝袜在线亚洲一区| 夜夜嗨一区二区| 国产精品极品在线观看| 成人午夜国产| 国产一卡不卡| 欧美特黄一级| 久久av影视| 石原莉奈一区二区三区在线观看| 欧美国产精品| 美女91精品| 久久伊人久久| 视频一区免费在线观看| 97精品一区| 日本成人一区二区| 亚洲精品在线影院|