摘要:簡介是才有的新功能,它是用來導(dǎo)出或提取出關(guān)于類方法屬性參數(shù)等的詳細(xì)信息,包括注釋。
簡介
PHP Reflection API是PHP5才有的新功能,它是用來導(dǎo)出或提取出關(guān)于類、方法、屬性、參數(shù)等的詳細(xì)信息,包括注釋。
class Reflection { } interface Reflector { } class ReflectionException extends Exception { } class ReflectionFunction implements Reflector { } class ReflectionParameter implements Reflector { } class ReflectionMethod extends ReflectionFunction { } class ReflectionClass implements Reflector { } class ReflectionObject extends ReflectionClass { } class ReflectionProperty implements Reflector { } class ReflectionExtension implements Reflector { }
用得比較多的就只有兩個ReflectionClass與ReflectionObject,兩個的用法都一樣,只是前者針對類,后者針對對象,后者是繼承前者的類;然后其中又有一些屬性或方法能返回對應(yīng)的Reflection對象(ReflectionProperty以及ReflectionMethod)
ReflectionClass具體參考手冊:http://php.net/manual/zh/clas...
通過ReflectionClass,我們可以得到Person類的以下信息:
常量 Contants
屬性 Property Names
方法 Method Names
靜態(tài)屬性 Static Properties
命名空間 Namespace
Person類是否為final或者abstract
id; } public function setId($v){ $this->id = $v; } public function getName(){ return $this->name; } public function setName($v){ $this->name = $v; } public function getBiography(){ return $this->biography; } public function setBiography($v){ $this->biography = $v; } } //傳遞類名或?qū)ο筮M(jìn)來 $class = new ReflectionClass("appPerson"); //獲取屬性,不管該屬性是否public $properties = $class->getProperties(); foreach($properties as $property) { echo $property->getName()." "; } // 輸出: // _allowDynamicAttributes // id // name // biography //默認(rèn)情況下,ReflectionClass會獲取到所有的屬性,private 和 protected的也可以。如果只想獲取到private屬性,就要額外傳個參數(shù): /* * ReflectionProperty::IS_STATIC * ReflectionProperty::IS_PUBLIC * ReflectionProperty::IS_PROTECTED * ReflectionProperty::IS_PRIVATE */ //↓↓ 注意一個|組合: 獲得IS_PRIVATE或者IS_PROTECTED的屬性 $private_properties = $class->getProperties(ReflectionProperty::IS_PRIVATE|ReflectionProperty::IS_PROTECTED); foreach($private_properties as $property) { //↓↓如果該屬性是受保護(hù)的屬性; if($property->isProtected()) { // ↓↓ 獲取注釋 $docblock = $property->getDocComment(); preg_match("/ type=([a-z_]*) /", $property->getDocComment(), $matches); echo $matches[1]." "; } } // Output: // primary_autoincrement // varchar // text $data = array("id" => 1, "name" => "Chris", "biography" => "I am am a PHP developer"); foreach($data as $key => $value) { if(!$class->hasProperty($key)) { throw new Exception($key." is not a valid property"); } if(!$class->hasMethod("get".ucfirst($key))) { throw new Exception($key." is missing a getter"); } if(!$class->hasMethod("set".ucfirst($key))) { throw new Exception($key." is missing a setter"); } $object = new Person(); // http://php.net/manual/zh/class.reflectionmethod.php // getMethod 獲得一個該方法的reflectionmethod對象,然后使用里面的invoke方法; $setter = $class->getMethod("set".ucfirst($key)); $ok = $setter->invoke($object, $value); // Get the setter method and invoke it $getter = $class->getMethod("get".ucfirst($key)); $objValue = $getter->invoke($object); // Now compare if($value == $objValue) { echo "Getter or Setter has modified the data. "; } else { echo "Getter and Setter does not modify the data. "; } }getMethod and invoke
ReflectionClass::getMethod — 獲取一個類方法的 ReflectionMethod(可以理解為獲得這個類方法的控制權(quán),不管這個類方法是否是public)。
具體的參考:
http://php.net/manual/zh/clas...
http://php.net/manual/zh/refl...
isPublic()){ $reflectionMethod -> setAccessible(true); } /* * public mixed ReflectionMethod::invoke ( object $object [, mixed $parameter [, mixed $... ]] ) * 1. 獲得某個類方法的ReflectionMethod * 2. $object 該方法所在的類實(shí)例的對象,然后第二參數(shù)起對號入座到該方法的每個參數(shù); * 3. 通過invoke就可以執(zhí)行這個方法了 */ echo $reflectionMethod->invoke($obj, "GangGe","How","are you"); //也可以把參數(shù)作為數(shù)組傳進(jìn)來 echo $reflectionMethod -> invokeArgs($obj,array("GangGe","How","are you"));getProperty
獲得一個 ReflectionProperty 類實(shí)例 (同上,獲得該屬性的控制權(quán)) http://cn2.php.net/manual/zh/...
public mixed ReflectionProperty::getValue ([ object $object ] )
如果該獲得該實(shí)例的類屬性不是一個static的屬性,就必須傳該類的實(shí)例
getProperty("staticProperty")->getValue()); //靜態(tài)屬性可以不加參數(shù) var_dump($reflectionClass->getProperty("property")->getValue(new Foo)); //非靜態(tài)屬性必須加傳一個類實(shí)例 $reflectionProperty = $reflectionClass->getProperty("privateProperty"); //受保護(hù)的屬性就要通過setAccessible獲得其權(quán)限 $reflectionProperty->setAccessible(true); var_dump($reflectionProperty->getValue(new Foo));Example 模擬YII框架中控制器調(diào)用方法的實(shí)現(xiàn)
hasMethod($action)) { exit("Method $action does not existed!"); } // 取類的構(gòu)造函數(shù),返回的是ReflectionMethod對象 $constructor = $reflector->getConstructor(); // 取構(gòu)造函數(shù)的參數(shù),這是一個對象數(shù)組 $parameters = $constructor->getParameters(); // 遍歷參數(shù) foreach ($parameters as $key => $parameter) { // 獲取參數(shù)聲明的類 $injector = new ReflectionClass($parameter->getClass()->name); // 實(shí)例化參數(shù)聲明類并填入?yún)?shù)列表 $parameters[$key] = $injector->newInstance(); //實(shí)例化$parameter->getClass()->name類 } // 使用參數(shù)列表實(shí)例 controller 類 $instance = $reflector->newInstanceArgs($parameters); // 執(zhí)行 $instance->$action(); class HelloController { private $model; public function __construct(TestModel $model) { $this->model = $model; } public function actionWorld() { echo $this->model->property, PHP_EOL; } } class TestModel { public $property = "property"; }TP框架中實(shí)現(xiàn)前后控制器
isPublic()) { $class = new ReflectionClass("BlogAction"); // 執(zhí)行前置方法 if ($class->hasMethod("_before_detail")) { $beforeMethod = $class->getMethod("_before_detail"); if ($beforeMethod->isPublic()) { $beforeMethod->invoke($instance); } } $method->invoke(new BlogAction); // 執(zhí)行后置方法 if ($class->hasMethod("_after_detail")) { $beforeMethod = $class->getMethod("_after_detail"); if ($beforeMethod->isPublic()) { $beforeMethod->invoke($instance); } } } // 執(zhí)行帶參數(shù)的方法 $method = new ReflectionMethod("BlogAction", "test"); $params = $method->getParameters(); foreach ($params as $param) { $paramName = $param->getName(); if (isset($_REQUEST[$paramName])) { $args[] = $_REQUEST[$paramName]; } elseif ($param->isDefaultValueAvailable()) { $args[] = $param->getDefaultValue(); } } if (count($args) == $method->getNumberOfParameters()) { $method->invokeArgs($instance, $args); } else { echo "parameters is wrong!"; }其他參考
/** * 執(zhí)行App控制器 */ public function execApp() { // 創(chuàng)建action控制器實(shí)例 $className = MODULE_NAME . "Controller"; $namespaceClassName = "apps" . APP_NAME . "controller" . $className; load_class($namespaceClassName, false); if (!class_exists($namespaceClassName)) { throw new Exception("Oops! Module not found : " . $namespaceClassName); } $controller = new $namespaceClassName(); // 獲取當(dāng)前操作名 $action = ACTION_NAME; // 執(zhí)行當(dāng)前操作 //call_user_func(array(&$controller, $action)); // 其實(shí)吧,用這個函數(shù)足夠啦!!! try { $methodInfo = new ReflectionMethod($namespaceClassName, $action); if ($methodInfo->isPublic() && !$methodInfo->isStatic()) { $methodInfo->invoke($controller); } else { // 操作方法不是public類型,拋出異常 throw new ReflectionException(); } } catch (ReflectionException $e) { // 方法調(diào)用發(fā)生異常后,引導(dǎo)到__call方法處理 $methodInfo = new ReflectionMethod($namespaceClassName, "__call"); $methodInfo->invokeArgs($controller, array($action, "")); } return; }
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/31355.html
摘要:而依賴倒置原則的思想是,上層不應(yīng)該依賴下層,應(yīng)依賴接口。上面通過構(gòu)造函數(shù)注入對象的方式,就是最簡單的依賴注入當(dāng)然注入不僅可以通過構(gòu)造函數(shù)注入,也可以通過屬性注入,上面你可以通過一個來動態(tài)為這個屬性賦值。 依賴倒置和控制反轉(zhuǎn)是一種編程思想,而依賴注入就是通過服務(wù)容器實(shí)現(xiàn)這種面向接口或者是面向抽象編程的思想 概念理解 依賴倒置原則 依賴倒置是一種軟件設(shè)計思想,在傳統(tǒng)軟件中,上層代碼依賴于下...
摘要:概述字節(jié)碼緩存不是的新特性,有很多獨(dú)立的擴(kuò)展可以實(shí)現(xiàn),比如和等,但是截至目前這些擴(kuò)展都沒有集成到內(nèi)核,從開始,內(nèi)置了字節(jié)碼緩存功能,名為。開始之前,我們先來看看什么是字節(jié)碼緩存,以及字節(jié)碼緩存的作用是什么。該函數(shù)將重置整個字節(jié)碼緩存。 概述 字節(jié)碼緩存不是PHP的新特性,有很多獨(dú)立的擴(kuò)展可以實(shí)現(xiàn),比如APC、eAccelerator和Xache等,但是截至目前這些擴(kuò)展都沒有集成到PHP...
摘要:通過生成器來生成關(guān)聯(lián)數(shù)組下面每一行是用分號分割的字段組合,第一個字段將被用作鍵名。正常來說,產(chǎn)生的是一個,它的成員變量與函數(shù)不存在別名引用關(guān)系。關(guān)鍵字在的版本,生成器允許從其他生成器,可迭代對象或數(shù)組通過關(guān)鍵字來生成對應(yīng)的值輸出 一般你在迭代一組數(shù)據(jù)的時候,需要創(chuàng)建一個數(shù)據(jù),假設(shè)數(shù)組很大,則會消耗很大性能,甚至造成內(nèi)存不足。 //Fatal error: Allowed memory ...
摘要:實(shí)例化對象里面的所在哪個類就返回哪個類。訪問的是當(dāng)前類有點(diǎn)像因?yàn)槠涫抢^承了的方法,而調(diào)用的。由此可見,他們的區(qū)別只有在繼承中才能體現(xiàn)出來,如果沒有任何繼承,那么這兩者是沒有區(qū)別的。但如果是在靜態(tài)方法內(nèi)本類的話,最好還是用 以static::來調(diào)用,是在運(yùn)行的那個時刻才執(zhí)行綁定操作; 父類中有個方法是延遲綁定的,在子類::調(diào)用這個方法的時候它又回到調(diào)用的子類開始向上找; exampl...
摘要:可以在任何時候啟用和禁用斷言驗(yàn)證,因此可以在測試時啟用斷言,而在部署時禁用斷言。會檢查指定的并在結(jié)果為時采取適當(dāng)?shù)男袆右暥āV械臄嘌韵蚝蠹嬗貌⒃鰪?qiáng)之前的的方法。它使得在生產(chǎn)環(huán)境中啟用斷言為零成本,并且提供當(dāng)斷言失敗時拋出特定異常的能力。 簡述 編寫代碼時,我們總是會做出一些假設(shè),斷言就是用于在代碼中捕捉這些假設(shè),可以將斷言看作是異常處理的一種高級形式。程序員斷言在程序中的某個特定點(diǎn)該...
閱讀 5199·2021-10-15 09:42
閱讀 1605·2021-09-22 16:05
閱讀 3260·2021-09-22 15:57
閱讀 3396·2019-12-27 12:06
閱讀 966·2019-08-29 15:16
閱讀 2879·2019-08-26 12:24
閱讀 379·2019-08-26 12:02
閱讀 1884·2019-08-23 16:00