<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                ## 簡介 PHP Reflection API是PHP5才有的新功能,它是用來導出或提取出關于類、方法、屬性、參數等的詳細信息,包括注釋。 ```php 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`,兩個的用法都一樣,只是前者針對類,后者針對對象,后者是繼承前者的類;然后其中又有一些屬性或方法能返回對應的`Reflection`對象(ReflectionProperty以及ReflectionMethod) ### ReflectionClass 具體參考手冊:http://php.net/manual/zh/class.reflectionclass.php 通過ReflectionClass,我們可以得到Person類的以下信息: - 常量 Contants - 屬性 Property Names - 方法 Method Names - 靜態屬性 Static Properties - 命名空間 Namespace - Person類是否為final或者abstract ``` <?php namespace app; class Person{ /** * For the sake of demonstration, we"re setting this private */ private $_allowDynamicAttributes = false; /** type=primary_autoincrement */ protected $id = 0; /** type=varchar length=255 null */ protected $name; /** type=text null */ protected $biography; public function getId(){ return $this->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; } } //傳遞類名或對象進來 $class = new \ReflectionClass('app\Person'); //獲取屬性,不管該屬性是否public $properties = $class->getProperties(); foreach($properties as $property) { echo $property->getName()."\n"; } // 輸出: // _allowDynamicAttributes // id // name // biography //默認情況下,ReflectionClass會獲取到所有的屬性,private 和 protected的也可以。如果只想獲取到private屬性,就要額外傳個參數: /* * 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) { //↓↓如果該屬性是受保護的屬性; if($property->isProtected()) { // ↓↓ 獲取注釋 $docblock = $property->getDocComment(); preg_match('/ type\=([a-z_]*) /', $property->getDocComment(), $matches); echo $matches[1]."\n"; } } // 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.\n"; } else { echo "Getter and Setter does not modify the data.\n"; } } ``` #### getMethod and invoke `ReflectionClass::getMethod` — 獲取一個類方法的 **ReflectionMethod**(可以理解為獲得這個類方法的控制權,不管這個類方法是否是public)。 具體的參考: - http://php.net/manual/zh/class.reflectionmethod.php - http://php.net/manual/zh/reflectionmethod.invoke.php ```php <?php class HelloWorld { private function sayHelloTo($name,$arg1,$arg2) { return 'Hello ' . $name.' '.$arg1.' '.$arg2; } } $obj = new HelloWorld(); // 第一個參數可以是對象,也可以是類 $reflectionMethod = new ReflectionMethod($obj , 'sayHelloTo'); if(!$reflectionMethod -> isPublic()){ $reflectionMethod -> setAccessible(true); } /* * public mixed ReflectionMethod::invoke ( object $object [, mixed $parameter [, mixed $... ]] ) * 1. 獲得某個類方法的ReflectionMethod * 2. $object 該方法所在的類實例的對象,然后第二參數起對號入座到該方法的每個參數; * 3. 通過invoke就可以執行這個方法了 */ echo $reflectionMethod->invoke($obj, 'GangGe','How','are you'); //也可以把參數作為數組傳進來 echo $reflectionMethod -> invokeArgs($obj,array('GangGe','How','are you')); ``` #### getProperty 獲得一個 `ReflectionProperty` 類實例 (同上,獲得該屬性的控制權) http://cn2.php.net/manual/zh/class.reflectionproperty.php ##### getValue獲取屬性值 ``` public mixed ReflectionProperty::getValue ([ object $object ] ) ``` 如果該獲得該實例的類屬性**不是一個static的屬性,就必須傳該類的實例** ```php <?php class Foo { public static $staticProperty = 'foobar'; public $property = 'barfoo'; protected $privateProperty = 'foofoo'; } $reflectionClass = new ReflectionClass('Foo'); var_dump($reflectionClass->getProperty('staticProperty')->getValue()); //靜態屬性可以不加參數 var_dump($reflectionClass->getProperty('property')->getValue(new Foo)); //非靜態屬性必須加傳一個類實例 $reflectionProperty = $reflectionClass->getProperty('privateProperty'); //受保護的屬性就要通過setAccessible獲得其權限 $reflectionProperty->setAccessible(true); var_dump($reflectionProperty->getValue(new Foo)); ``` ### Example #### 模擬YII框架中控制器調用方法的實現 ```php <?php if (PHP_SAPI != 'cli') { exit('Please run it in terminal!'); } if ($argc < 3) { exit('At least 2 arguments needed!'); } $controller = ucfirst($argv[1]) . 'Controller'; $action = 'action' . ucfirst($argv[2]); // 檢查類是否存在 if (!class_exists($controller)) { exit("Class $controller does not existed!"); } // 獲取類的反射 $reflector = new ReflectionClass($controller); // 檢查方法是否存在 if (!$reflector->hasMethod($action)) { exit("Method $action does not existed!"); } // 取類的構造函數,返回的是ReflectionMethod對象 $constructor = $reflector->getConstructor(); // 取構造函數的參數,這是一個對象數組 $parameters = $constructor->getParameters(); // 遍歷參數 foreach ($parameters as $key => $parameter) { // 獲取參數聲明的類 $injector = new ReflectionClass($parameter->getClass()->name); // 實例化參數聲明類并填入參數列表 $parameters[$key] = $injector->newInstance(); //實例化$parameter->getClass()->name類 } // 使用參數列表實例 controller 類 $instance = $reflector->newInstanceArgs($parameters); // 執行 $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框架中實現前后控制器 ```php <?php class BlogAction { public function detail() { echo 'detail' . "\r\n"; } public function test($year = 2014, $month = 4, $day = 21) { echo $year . '--' . $month . '--' . $day . "\r\n"; } public function _before_detail() { echo __FUNCTION__ . "\r\n"; } public function _after_detail() { echo __FUNCTION__ . "\r\n"; } } // 執行detail方法 $method = new ReflectionMethod('BlogAction', 'detail'); $instance = new BlogAction(); // 進行權限判斷 if ($method->isPublic()) { $class = new ReflectionClass('BlogAction'); // 執行前置方法 if ($class->hasMethod('_before_detail')) { $beforeMethod = $class->getMethod('_before_detail'); if ($beforeMethod->isPublic()) { $beforeMethod->invoke($instance); } } $method->invoke(new BlogAction); // 執行后置方法 if ($class->hasMethod('_after_detail')) { $beforeMethod = $class->getMethod('_after_detail'); if ($beforeMethod->isPublic()) { $beforeMethod->invoke($instance); } } } // 執行帶參數的方法 $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!'; } ``` #### 其他參考 ```php /** * 執行App控制器 */ public function execApp() { // 創建action控制器實例 $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(); // 獲取當前操作名 $action = ACTION_NAME; // 執行當前操作 //call_user_func(array(&$controller, $action)); // 其實吧,用這個函數足夠啦!!! try { $methodInfo = new \ReflectionMethod($namespaceClassName, $action); if ($methodInfo->isPublic() && !$methodInfo->isStatic()) { $methodInfo->invoke($controller); } else { // 操作方法不是public類型,拋出異常 throw new \ReflectionException(); } } catch (\ReflectionException $e) { // 方法調用發生異常后,引導到__call方法處理 $methodInfo = new \ReflectionMethod($namespaceClassName, '__call'); $methodInfo->invokeArgs($controller, array($action, '')); } return; } ```
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看