<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>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                # 速查表 新版升級 ## 歷史回顧 我感嘆于laravel的生態完好,tp5的類api的缺失(以前thinkphp3時代,幫助公司用apigen NetBeans里生成過一個[3.1版本的api](http://www.thinkphp.cn/api/))。 ![](https://box.kancloud.cn/362d9e9b3a4adf2d87d00ef3b88e344a_1634x753.png) 在我走之后,估計沒人用NetBeans了 所以就沒人做升級。 然后我覺得laravel的速查表不錯,見下圖: ![](https://box.kancloud.cn/08ce1b130d60e7dd91cb2a2a84a106bf_1880x942.png) 于是就想到了把他移植到tp5上,作為自己回到thinkphp5開發上的第一個貢獻。 記得那個時候是清明前開始動手的。使用最土的,靜態頁面,一個個類手動去編輯。 后來發現類太多了,我每次在sublime 里 先打開一個類,復制出來臨時文件,處理好,粘貼到靜態index.html里,太麻煩了,要處理左側的導航,又要定位插入的位置。 于是乎在五一放假時 我換了個思路,我不搞靜態了,我搞動態的。 于是在海豚里建了一個插件, ![](https://box.kancloud.cn/9e59b717a605206c9d8524d2df22dd68_408x579.png) ![](https://box.kancloud.cn/151ea4077b21e19b8c5273df961a8bec_1572x283.png) ![](https://box.kancloud.cn/a2706b813b86185a7754188e9a4da023_1568x555.png) ![](https://box.kancloud.cn/a2c1a142688505b1561ce354df0d468e_1572x603.png) 以章節的形式添加。終于效率上去了,五一時候抽空把內容全補全了。 發布到了 掘金上,獲得了17個贊。 ![](https://box.kancloud.cn/00443be8b9c5c5e7ceed4ed55525fd82_350x209.png) ## 進擊的速查表 本來以為完成了。結果老大們太積極7月4日又發布了5.0.10,然后在開發5.1dev版。 既然老大把我的速查表都掛到了tp官網上。我也不能讓用的人等,看舊的5.0.7版、 可是我不想在人工去對比改了哪個類,增加還是刪除了哪些方法。20多章呢。 我想 “代碼的問題應該由代碼解決”。于是想到了php的注解、反射類。 正好項目用到了一個 **crada/php-apidoc** 的api文檔生成工具。 于是我就開始動手實現這通過類反射信息獲取方法的工程。 ### 反射的資料 > PHP 5 具有完整的反射 API,添加了對類、接口、函數、方法和擴展進行反向工程的能力。 此外,反射 API 提供了方法來取出函數、類和方法中的文檔注釋。 官網手冊提到了反射有這多類: Reflection ReflectionClass ReflectionZendExtension ReflectionExtension ReflectionFunction ReflectionFunctionAbstract ReflectionMethod ReflectionObject ReflectionParameter ReflectionProperty ReflectionType ReflectionGenerator Reflector ReflectionException ### 實現思路 ~~~ // TODO 獲取待處理的類命名空間數據 // TODO 遍歷類 反射 // TODO 獲取類的信息 (名稱、方法列表) // TODO 遍歷方法列表, 獲取方法的類型 和注釋 ~~~ 我看了一遍反射是先反射類 再找到方法 再找到方法的參數 #### 類的獲取 tp5的核心類 都在一個目錄 于是我想到了用glob遍歷 ~~~ public function get_core_class(){ $class_path = CORE_PATH; $before_cwd = getcwd(); chdir($class_path); $names = glob('*.php'); $ret = []; foreach ($names as $key => $name) { $ret[] = 'think\\'. str_ireplace('.php', '', $name); } chdir($before_cwd); return $ret; } ~~~ 反射類的初始化要傳的是類的實際命名空間路徑。 `$class= new\ReflectionClass($className);` 這樣。然后有以下方法: ReflectionClass::__construct — 初始化 ReflectionClass 類 ReflectionClass::export — 導出一個類 ReflectionClass::getConstant — 獲取定義過的一個常量 ReflectionClass::getConstants — 獲取一組常量 ReflectionClass::getConstructor — 獲取類的構造函數 ReflectionClass::getDefaultProperties — 獲取默認屬性 ReflectionClass::getDocComment — 獲取文檔注釋 ReflectionClass::getEndLine — 獲取最后一行的行數 ReflectionClass::getExtension — 根據已定義的類獲取所在擴展的 ReflectionExtension 對象 ReflectionClass::getExtensionName — 獲取定義的類所在的擴展的名稱 ReflectionClass::getFileName — 獲取定義類的文件名 ReflectionClass::getInterfaceNames — 獲取接口(interface)名稱 ReflectionClass::getInterfaces — 獲取接口 ReflectionClass::getMethod — 獲取一個類方法的 ReflectionMethod。 ReflectionClass::getMethods — 獲取方法的數組 ReflectionClass::getModifiers — 獲取類的修飾符 ReflectionClass::getName — 獲取類名 ReflectionClass::getNamespaceName — 獲取命名空間的名稱 ReflectionClass::getParentClass — 獲取父類 ReflectionClass::getProperties — 獲取一組屬性 ReflectionClass::getProperty — 獲取類的一個屬性的 ReflectionProperty ReflectionClass::getShortName — 獲取短名 ReflectionClass::getStartLine — 獲取起始行號 ReflectionClass::getStaticProperties — 獲取靜態(static)屬性 ReflectionClass::getStaticPropertyValue — 獲取靜態(static)屬性的值 ReflectionClass::getTraitAliases — 返回 trait 別名的一個數組 ReflectionClass::getTraitNames — 返回這個類所使用 traits 的名稱的數組 ReflectionClass::getTraits — 返回這個類所使用的 traits 數組 ReflectionClass::hasConstant — 檢查常量是否已經定義 ReflectionClass::hasMethod — 檢查方法是否已定義 ReflectionClass::hasProperty — 檢查屬性是否已定義 ReflectionClass::implementsInterface — 接口的實現 ReflectionClass::inNamespace — 檢查是否位于命名空間中 ReflectionClass::isAbstract — 檢查類是否是抽象類(abstract) ReflectionClass::isAnonymous — 檢查類是否是匿名類 ReflectionClass::isCloneable — 返回了一個類是否可復制 ReflectionClass::isFinal — 檢查類是否聲明為 final ReflectionClass::isInstance — 檢查類的實例 ReflectionClass::isInstantiable — 檢查類是否可實例化 ReflectionClass::isInterface — 檢查類是否是一個接口(interface) ReflectionClass::isInternal — 檢查類是否由擴展或核心在內部定義 ReflectionClass::isIterateable — 檢查是否可迭代(iterateable) ReflectionClass::isSubclassOf — 檢查是否為一個子類 ReflectionClass::isTrait — 返回了是否為一個 trait ReflectionClass::isUserDefined — 檢查是否由用戶定義的 ReflectionClass::newInstance — 從指定的參數創建一個新的類實例 ReflectionClass::newInstanceArgs — 從給出的參數創建一個新的類實例。 ReflectionClass::newInstanceWithoutConstructor — 創建一個新的類實例而不調用它的構造函數 ReflectionClass::setStaticPropertyValue — 設置靜態屬性的值 ReflectionClass::__toString — 返回 ReflectionClass 對象字符串的表示形式。 這些方法看著是靜態,其實可以 **$class->getShortName()** 直接使用。 我主要需要拿到類簡寫名和方法。 ~~~ public function generate($classNames){ config('default_return_type', 'json'); // TODO 獲取待處理的類命名空間數據 // TODO 遍歷類 反射 // TODO 獲取類的信息 (名稱、方法列表) // TODO 遍歷方法列表, 獲取方法的類型 和注釋 $outputs = []; foreach ($classNames as $k => $className) { $class= new\ReflectionClass($className); $key = $class->getShortName(); // dump($key); $outputs[$key] = $this->getClassAnnotation($class); } return $outputs; } ~~~ getClassAnonation 方法就是我用來獲取類的全部方法的信息的方法。 #### 方法相關 拿到反射類之后 想獲取反射方法,得實例化 ReflectionMethod 類。 ~~~ // 獲取類的注釋信息 public function getClassAnnotation($class){ $ret = [ 'hasPublicMethods'=>0, ]; $ret['name'] = $class->getName(); $methods = $class->getMethods(); foreach ($methods as $key => $method) { $class = $method->class; $method_name = $method->name; $rm = new \ReflectionMethod($class, $method_name); // 忽略構造和析構 if($rm->isConstructor() || $rm->isDestructor()){ continue; } $foo = []; $foo['docComment'] = $rm->getDocComment(); $foo['docComment_formated'] = $this->parseMethodDoc($foo['docComment']); $foo['args'] = $rm->getParameters(); $foo['args_formated'] = $this->parseParameters($class, $method_name, $foo['args']); if($rm->isPublic()){ $type = $rm->isStatic()? 'public_static' : 'public_public'; }else{ $type = $rm->isStatic()? 'private_static' : 'private_public'; } // 只在hasPublicMethods 為0時更新值,保證設置1后不會被復寫為0 if(empty($ret['hasPublicMethods'])){ $ret['hasPublicMethods'] = stripos($type, '_public') !== false; } $foo['type'] = $type; $ret['methods'][$method_name] = $foo; } return $ret; // $className = 'think\\App'; // $class = new \ReflectionClass($className); // config('default_return_type', 'json'); // 類名 // return $class->name; // ReflectionClass 實例的一個字符串表示形式 // return $class->__toString(); // 同上 // return \ReflectionClass::export($className, 1); // 獲取類常量 // return json_encode($class->getConstants()); // 獲取構造方法 // return $class->getConstructor(); // 類名相關 // var_dump($class->inNamespace()); // var_dump($class->getName()); // var_dump($class->getNamespaceName()); // var_dump($class->getShortName()); # 文件相關 // getFileName // getExtensionName // 屬性相關 // return $class->getDefaultProperties(); // return $class->getProperties(\ReflectionProperty::IS_PUBLIC | \ReflectionProperty::IS_PROTECTED); // const integer IS_STATIC = 1 ; // const integer IS_PUBLIC = 256 ; // const integer IS_PROTECTED = 512 ; // const integer IS_PRIVATE = 1024 ; // return $class->getStaticProperties(); // 類注釋 // return $class->getDocComment(); } ~~~ 先獲取全部的類方法: $class->getMethods(); 官網的例子: ~~~ array(3) { [0]=> &object(ReflectionMethod)#2 (2) { ["name"]=> string(11) "firstMethod" ["class"]=> string(5) "Apple" } [1]=> &object(ReflectionMethod)#3 (2) { ["name"]=> string(12) "secondMethod" ["class"]=> string(5) "Apple" } [2]=> &object(ReflectionMethod)#4 (2) { ["name"]=> string(11) "thirdMethod" ["class"]=> string(5) "Apple" } } ~~~ 在獲取時還可以傳屬性類型進行過濾: ~~~ <?php class Apple { public function firstMethod() { } final protected function secondMethod() { } private static function thirdMethod() { } } $class = new ReflectionClass('Apple'); $methods = $class->getMethods(ReflectionMethod::IS_STATIC | ReflectionMethod::IS_FINAL); var_dump($methods); ?> ~~~ 拿到方法后,我們需要獲得類的方法的公有私有、靜態等屬性。 ![](https://box.kancloud.cn/8e5426f80c5fd4ff970a167964fb3102_287x529.png) 因為我在顯示時做了方法不同類型的區分演示。 ~~~ $rm = new \ReflectionMethod($class, $method_name); // 忽略構造和析構 if($rm->isConstructor() || $rm->isDestructor()){ continue; } ~~~ 先過濾掉構造和析構方法。 ~~~ $foo = []; $foo['docComment'] = $rm->getDocComment(); $foo['docComment_formated'] = $this->parseMethodDoc($foo['docComment']); $foo['args'] = $rm->getParameters(); $foo['args_formated'] = $this->parseParameters($class, $method_name, $foo['args']); ~~~ 我先獲取了原有方法的文檔信息和參數信息,并且按照我需要的進行格式化。 獲取參數的要注意,返回的是參數數組 官方示例: ~~~ <?php public static function fire_theme_method($class, $method) { $fire_args=array(); $reflection = new ReflectionMethod($class, $method); foreach($reflection->getParameters() AS $arg) { if($_REQUEST[$arg->name]) $fire_args[$arg->name]=$_REQUEST[$arg->name]; else $fire_args[$arg->name]=null; } return call_user_func_array(array($class, $method), $fire_args); } ?> ~~~ 主要咱獲取到參數名稱 然后結合methodName 去實例化 ReflectionParameter 來獲取參數信息 #### 類的參數信息 ~~~ public function parseParameters($class, $method, $args){ if($args){ $args_str = []; foreach ($args as $key => $arg) { $p = new \ReflectionParameter(array($class, $method), $key); // 判斷是否引用參數 if($p->isPassedByReference()){ $arg_str_new = "&\$".$p->getName(); }else{ $arg_str_new = "\$".$p->getName(); } if ($p->isOptional() && $p->isDefaultValueAvailable()) { $a_clsss = $class; // 獲取某些內部類的參數會拋異常,且異常時$class會變化不是我們想知道的哪個類方法一場了 try{ $defaul = $p->getDefaultValue(); $arg_str_new .= is_array($defaul) ? ' = '. '[]': ' = '. var_export($defaul, 1); }catch(\Exception $e){ trace($p->isVariadic()); trace($a_clsss.'/'.$method.'_'.$key); } } $args_str[] = $arg_str_new; } return implode(', ', $args_str); } return ''; } ~~~ 有的方法沒參數直接返回空,有的有參數,咱們想拼接處 參數字符串 比如 ~~~ <?php class A{ function foo($a){ } } ~~~ php不會返回` foo($a)`這串的。得自己處理 主要留意參數的 是否有默認值、是否引用 * getName * isOptional * isDefaultValueAvailable * getDefaultValue 在獲取默認值參數的時候 我發現有的時候會拋異常,而且都報的是內部類的。 所以一定要try catch 去獲取默認值。 至此 整個獲取某些類的 方法及方法注釋和參數信息 的功能全部實現。 大家如果想獲取某一組class的 速查表 只需 修改get_core_class返回值,只要是tp5里自動加載的類。都可以解析。 整體思路,根據類數組獲取方法->方法文檔、獲取參數->獲取參數信息 這樣,我就可以安心的偷懶了。下次tp升級,我直接composer update一下,刷新一下首頁,拿到靜態html 更新到我的 gh-pages 分支。就完成了新框架速寫表的更新。 一勞永逸啊。 ## 尾聲 具體源碼參考 :https://github.com/yangweijie/thinkphp-lts 查看速查表 直接:https://yangweijie.github.io/thinkphp-lts/ ![](https://box.kancloud.cn/5cc127b3019ca3971a3107237d9569f8_1872x967.png) 歡迎給我提供建議。
                  <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>

                              哎呀哎呀视频在线观看