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

                ~~~ <?php // +---------------------------------------------------------------------- // | ThinkPHP [ WE CAN DO IT JUST THINK ] // +---------------------------------------------------------------------- // | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved. // +---------------------------------------------------------------------- // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) // +---------------------------------------------------------------------- // | Author: liu21st <liu21st@gmail.com> // +---------------------------------------------------------------------- namespace think; //基于 最基礎的think命名空間 use think\exception\ClassNotFoundException; //use think\exception\ClassNotFoundException; //運行 未發現類 異常 class Loader {//加載類 protected static $instance = [];//受保護靜態的類名映射 也就是實例化了 // 類名映射 protected static $map = [];//類映射 存儲位置 映射 存儲關系 // 命名空間別名 protected static $namespaceAlias = [];//別名 命名空間 別名 // PSR-4 private static $prefixLengthsPsr4 = []; private static $prefixDirsPsr4 = []; private static $fallbackDirsPsr4 = []; // PSR-0 private static $prefixesPsr0 = []; private static $fallbackDirsPsr0 = []; // 自動加載的文件 private static $autoloadFiles = []; // 自動加載 public static function autoload($class)//這個就加載文件 {//自動加載類//加載一個class // 檢測命名空間別名 if (!empty(self::$namespaceAlias)) {//如果有命名空間 $namespace = dirname($class);//通過類名的路徑來命名空間 if (isset(self::$namespaceAlias[$namespace])) {//如果有別名,通過路徑來dirname $original = self::$namespaceAlias[$namespace] . '\\' . basename($class); //鏈接為最新的$original if (class_exists($original)) {//檢查類是否已定義 return class_alias($original, $class, false);//為這個類創建別名 // 如果存在這個 真實的 class_alias 別名: 然后 進入到對應到的 class } } } if ($file = self::findFile($class)) {//查找這個類名的文件 // Win環境嚴格區分大小寫 if (IS_WIN && pathinfo($file, PATHINFO_FILENAME) != pathinfo(realpath($file), PATHINFO_FILENAME)) { return false; } __include_file($file);//加載文件(下面有方法 ) return true; } }// 這個函數的意思,基本上就是 自動加載對應的文件 類文件 /** * 查找文件 * @param $class * @return bool */ private static function findFile($class)//查找文件 { if (!empty(self::$map[$class])) {//如果文件存在類映射 // 類庫映射 return self::$map[$class];//返回類名映射 } // 查找 PSR-4 $logicalPathPsr4 = strtr($class, '\\', DS) . EXT;//返回第一節數據 $first = $class[0];//獲取最新的數據 if (isset(self::$prefixLengthsPsr4[$first])) {//如果設置了這個預定義變量 foreach (self::$prefixLengthsPsr4[$first] as $prefix => $length) {//循環 if (0 === strpos($class, $prefix)) {//找到文件//strops查找字符串首次出現的位置 foreach (self::$prefixDirsPsr4[$prefix] as $dir) {//loop目錄 if (is_file($file = $dir . DS . substr($logicalPathPsr4, $length))) { return $file; }//如果文件存在就返回 } } } } // 查找 PSR-4 fallback dirs foreach (self::$fallbackDirsPsr4 as $dir) { if (is_file($file = $dir . DS . $logicalPathPsr4)) {//如果有fallback Dirs Psr4 循環展示 return $file; } } //如果有這個標準下的文件,返回文件 // 查找 PSR-0 if (false !== $pos = strrpos($class, '\\')) {//如果這里//strrpos計算字符串在目標字符串中最后一次出現的位置 // namespaced class name $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) . strtr(substr($logicalPathPsr4, $pos + 1), '_', DS); } else { // PEAR-like class name $logicalPathPsr0 = strtr($class, '_', DS) . EXT;//這里獲取另外一種方式 } if (isset(self::$prefixesPsr0[$first])) {//如果含有這個first 就是class里面的第一個 foreach (self::$prefixesPsr0[$first] as $prefix => $dirs) {//循環這里的dir if (0 === strpos($class, $prefix)) {//如果開始就存在這個$prefix foreach ($dirs as $dir) {//循環數據 if (is_file($file = $dir . DS . $logicalPathPsr0)) { return $file; } } } } }//有這樣的格式的數據,直接返回,而且,是循環的 // 查找 PSR-0 fallback dirs foreach (self::$fallbackDirsPsr0 as $dir) { if (is_file($file = $dir . DS . $logicalPathPsr0)) { return $file; } } return self::$map[$class] = false;//否則返回數據 } // 注冊classmap public static function addClassMap($class, $map = '') {//addClassMap類文件映射,支持數組,或者key value兩種方式 if (is_array($class)) { self::$map = array_merge(self::$map, $class);//array_merge 合并數組 } else { self::$map[$class] = $map; } } // 注冊命名空間 public static function addNamespace($namespace, $path = '') {//新增命名空間注冊 //特點:就是支持key value和數組賦值方式 if (is_array($namespace)) { foreach ($namespace as $prefix => $paths) { self::addPsr4($prefix . '\\', rtrim($paths, DS), true); } } else { self::addPsr4($namespace . '\\', rtrim($path, DS), true); } } // 添加Ps0空間 private static function addPsr0($prefix, $paths, $prepend = false) { //如果不存在prefix //把數據給$fallbackDirsPsr0 //prepend代表:是配置大于約定還是,約定大于配置,這個是常用的手法,不錯! if (!$prefix) {//如果沒有對應的namespace或者前綴 if ($prepend) {//默認的是false,傳入的是true 正常調試就是執行這個 self::$fallbackDirsPsr0 = array_merge( (array)$paths, self::$fallbackDirsPsr0 );//充分使用了array_merge對于不同位置的覆蓋方向不一樣,導致的。 } else { self::$fallbackDirsPsr0 = array_merge( self::$fallbackDirsPsr0, (array)$paths ); } //直接返回了 不會向下執行了 return;//同樣深層次支持 } //如果存在first //配置到對應的prefix $first = $prefix[0];//如果有這個first if (!isset(self::$prefixesPsr0[$first][$prefix])) {//如果沒有這個 self::$prefixesPsr0[$first][$prefix] = (array)$paths;//設置,然后返回 return; } //默認,有設置的,合并 if ($prepend) { self::$prefixesPsr0[$first][$prefix] = array_merge( (array)$paths, self::$prefixesPsr0[$first][$prefix] ); } else { self::$prefixesPsr0[$first][$prefix] = array_merge( self::$prefixesPsr0[$first][$prefix], (array)$paths ); } } // 添加Psr4空間 private static function addPsr4($prefix, $paths, $prepend = false) {//同樣的代碼 if (!$prefix) { // Register directories for the root namespace.為根名稱空間注冊目錄。 if ($prepend) { self::$fallbackDirsPsr4 = array_merge( (array)$paths, self::$fallbackDirsPsr4 ); } else { self::$fallbackDirsPsr4 = array_merge( self::$fallbackDirsPsr4, (array)$paths ); } } elseif (!isset(self::$prefixDirsPsr4[$prefix])) {//注冊如果沒有這些 // Register directories for a new namespace.為一個新的名稱空間注冊目錄。 $length = strlen($prefix); if ('\\' !== $prefix[$length - 1]) {//長度 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); } self::$prefixLengthsPsr4[$prefix[0]][$prefix] = $length; self::$prefixDirsPsr4[$prefix] = (array)$paths; } elseif ($prepend) { // Prepend directories for an already registered namespace.已注冊名稱空間的預pend目錄。 self::$prefixDirsPsr4[$prefix] = array_merge( (array)$paths, self::$prefixDirsPsr4[$prefix] ); } else { // Append directories for an already registered namespace.為已經注冊的名稱空間添加目錄。 self::$prefixDirsPsr4[$prefix] = array_merge( self::$prefixDirsPsr4[$prefix], (array)$paths ); } } // 注冊命名空間別名 public static function addNamespaceAlias($namespace, $original = '') { if (is_array($namespace)) { self::$namespaceAlias = array_merge(self::$namespaceAlias, $namespace); } else { self::$namespaceAlias[$namespace] = $original; } } /** * 使用這個自動加載函數 * 注冊自動加載機制 * @param string $autoload */ public static function register($autoload = '') {// 重點!重點!重點!重點!重點!重點!重點!重點!重點!重點!重點! // 注冊系統自動加載 spl_autoload_register($autoload ?: 'think\\Loader::autoload', true, true); // spl_autoload_register 將函數注冊到SPL __autoload函數隊列中。如果該隊列中的函數尚未激活,則激活它們。 // 進行 系統加載 函數 自動注冊 // 自動 加載文件 // 特點,就是 用的時候,自動加載, 優于當年的 全部加載,這個也是他宣傳的按需加載! // 如果沒有 對應需要 提前加載的東西,默認的 就是 檢測文件是否正確, // 直接使用 return include 進行 // 通過 class 名字,按照 不同的 標準 進行 加載, 更多的國際化了,你進步了 // 其實這個里面的 核心 技術應該是 對應 不同標準的 Ps0 跟 Ps4 標準的 路徑的獲取 // 實現不同 標準下的 類文件加載 // 這個挺關鍵 // 注冊命名空間定義 self::addNamespace([ 'think' => LIB_PATH . 'think' . DS, 'behavior' => LIB_PATH . 'behavior' . DS, 'traits' => LIB_PATH . 'traits' . DS, ]);//開始對命名空間進行配置 // 加載類庫映射文件 if (is_file(RUNTIME_PATH . 'classmap' . EXT)) { self::addClassMap(__include_file(RUNTIME_PATH . 'classmap' . EXT)); } // Composer自動加載支持 if (is_dir(VENDOR_PATH . 'composer')) { self::registerComposerLoader(); } // 自動加載extend目錄 self::$fallbackDirsPsr4[] = rtrim(EXTEND_PATH, DS); } // 注冊composer自動加載 private static function registerComposerLoader() {//默認沒有不會執行 if (is_file(VENDOR_PATH . 'composer/autoload_namespaces.php')) { $map = require VENDOR_PATH . 'composer/autoload_namespaces.php'; foreach ($map as $namespace => $path) { self::addPsr0($namespace, $path); } }//加載命名空間 if (is_file(VENDOR_PATH . 'composer/autoload_psr4.php')) { $map = require VENDOR_PATH . 'composer/autoload_psr4.php'; foreach ($map as $namespace => $path) { self::addPsr4($namespace, $path); } }//加載Psr4標準 if (is_file(VENDOR_PATH . 'composer/autoload_classmap.php')) { $classMap = require VENDOR_PATH . 'composer/autoload_classmap.php'; if ($classMap) { self::addClassMap($classMap); } }//加載classmap if (is_file(VENDOR_PATH . 'composer/autoload_files.php')) { $includeFiles = require VENDOR_PATH . 'composer/autoload_files.php'; foreach ($includeFiles as $fileIdentifier => $file) { if (empty(self::$autoloadFiles[$fileIdentifier])) { __require_file($file); self::$autoloadFiles[$fileIdentifier] = true; } } }//加載文件 } /** * 導入所需的類庫 同java的Import 本函數有緩存功能 * @param string $class 類庫命名空間字符串 * @param string $baseUrl 起始路徑 * @param string $ext 導入的文件擴展名 * @return boolean */ public static function import($class, $baseUrl = '', $ext = EXT) {//導入類文件 static $_file = [];//靜態文件倉庫 $key = $class . $baseUrl;//key文件 $class = str_replace(['.', '#'], [DS, '.'], $class);//處理class if (isset($_file[$key])) { return true; }//如果加載過了這個文件,就直接 if (empty($baseUrl)) {//如果起始路徑為空,就是默認值 list($name, $class) = explode(DS, $class, 2);//返回 類的 前面兩個數組 if (isset(self::$prefixDirsPsr4[$name . '\\'])) {//如果存在這個Psr4 // 注冊的命名空間 $baseUrl = self::$prefixDirsPsr4[$name . '\\']; } elseif ('@' == $name) { //加載當前模塊應用類庫 $baseUrl = App::$modulePath;//獲取@方式 } elseif (is_dir(EXTEND_PATH . $name)) { $baseUrl = EXTEND_PATH . $name . DS;//獲取基礎地址 } else { // 加載其它模塊的類庫 $baseUrl = APP_PATH . $name . DS; } } elseif (substr($baseUrl, -1) != DS) { $baseUrl .= DS; }//獲取baseUrl // 如果類存在 則導入類庫文件 if (is_array($baseUrl)) {//如果基礎地址為baseUrl foreach ($baseUrl as $path) { $filename = $path . DS . $class . $ext;//baseUrl if (is_file($filename)) { break;//找到了文件就退出 } } } else { $filename = $baseUrl . $class . $ext; } if (!empty($filename) && is_file($filename)) {// 如果 沒有 文件, 如果有這個文件 // 開啟調試模式Win環境嚴格區分大小寫 if (IS_WIN && pathinfo($filename, PATHINFO_FILENAME) != pathinfo(realpath($filename), PATHINFO_FILENAME)) { return false; }// 如果路徑 不行 __include_file($filename);// 加載文件 $_file[$key] = true;// 執行 狀態 return true; } return false; } /** * 實例化(分層)模型 * @param string $name Model名稱 * @param string $layer 業務層名稱 * @param bool $appendSuffix 是否添加類名后綴 * @param string $common 公共模塊名 * @return object * @throws ClassNotFoundException */ public static function model($name = '', $layer = 'model', $appendSuffix = false, $common = 'common') {// 獲取對應的信息 $guid = $name . $layer; if (isset(self::$instance[$guid])) { return self::$instance[$guid]; }// 不同的 層 跟 不同的 名字 就可以確定 不同的 model // 對應到 不同的 key if (false !== strpos($name, '\\')) { $class = $name; $module = Request::instance()->module(); } else { if (strpos($name, '/')) {// 如果你的名字不純潔 那么就要處理你 list($module, $name) = explode('/', $name, 2);//默認給到的 就是 list 方式 } else { $module = Request::instance()->module();// 否則 應該會自動加載了,這個位置,不是初始化調用的地方 } $class = self::parseClass($module, $layer, $name, $appendSuffix);// 獲取到對應的 類 名 , this class name } if (class_exists($class)) {// 找到的這個class變量,如果是個 class 的話,就使用他 $model = new $class(); // 好用法 } else { $class = str_replace('\\' . $module . '\\', '\\' . $common . '\\', $class); if (class_exists($class)) {// 如果可以了 $model = new $class();// 執行他 } else {// 否則的話 拋出 類 異常 // 這里可以補充一下, 其實應該是 model class not exists: throw new ClassNotFoundException('class not exists:' . $class, $class); } } self::$instance[$guid] = $model;// 存入 key value 關鍵字 return $model;// 返回 數據 } /** * 實例化(分層)控制器 格式:[模塊名/]控制器名 * @param string $name 資源地址 * @param string $layer 控制層名稱 * @param bool $appendSuffix 是否添加類名后綴 * @param string $empty 空控制器名稱 * @return object * @throws ClassNotFoundException */ public static function controller($name, $layer = 'controller', $appendSuffix = false, $empty = '') { if (false !== strpos($name, '\\')) { $class = $name; $module = Request::instance()->module(); } else { // 第一步: 獲取對應的 model // 通過 不同的 方式 1 // 方式2 if (strpos($name, '/')) { list($module, $name) = explode('/', $name); } else { $module = Request::instance()->module(); } // 第二步: 獲取 class $class = self::parseClass($module, $layer, $name, $appendSuffix); } // 第三步:對獲取的class 進行 驗證,存在,就 if (class_exists($class)) { return App::invokeClass($class);// 返回 } elseif ($empty && class_exists($emptyClass = self::parseClass($module, $layer, $empty, $appendSuffix))) { return new $emptyClass(Request::instance());// 返回空的 } else { throw new ClassNotFoundException('class not exists:' . $class, $class); // 看來進步了,沒有報錯 } } /** * 實例化驗證類 格式:[模塊名/]驗證器名 * @param string $name 資源地址 * @param string $layer 驗證層名稱 * @param bool $appendSuffix 是否添加類名后綴 * @param string $common 公共模塊名 * @return object|false * @throws ClassNotFoundException */ public static function validate($name = '', $layer = 'validate', $appendSuffix = false, $common = 'common') { // 進行驗證,驗證類型: // 名字 層名字 前綴 $name = $name ?: Config::get('default_validate');// 獲取驗證規則 地址 if (empty($name)) {// empty $name 如果文件為空,直接返回 return new Validate;// 新的 驗證類 Validate 新的驗證類 } $guid = $name . $layer; if (isset(self::$instance[$guid])) {// 存在就直接返回 return self::$instance[$guid]; }// 如果已經 驗證了 if (false !== strpos($name, '\\')) { $class = $name; $module = Request::instance()->module(); } else { if (strpos($name, '/')) { list($module, $name) = explode('/', $name); } else { $module = Request::instance()->module(); } // 獲取類 $class = self::parseClass($module, $layer, $name, $appendSuffix); } if (class_exists($class)) {// 如果類存在 $validate = new $class;// 生成 新類 } else { $class = str_replace('\\' . $module . '\\', '\\' . $common . '\\', $class);// 如果 獲取類 if (class_exists($class)) { $validate = new $class;// 返回新 類 } else { throw new ClassNotFoundException('class not exists:' . $class, $class); } }// 你懂的 類不存在了 self::$instance[$guid] = $validate;// 存檔 備查詢 return $validate; } /** * 數據庫初始化 并取得數據庫類實例 * @param mixed $config 數據庫配置 * @param bool|string $name 連接標識 true 強制重新連接 * @return \think\db\Connection */ public static function db($config = [], $name = false) { return Db::connect($config, $name); }// 數據庫 初始化 并取得 數據庫 實例 /** * 遠程調用模塊的操作方法 參數格式 [模塊/控制器/]操作 * @param string $url 調用地址 * @param string|array $vars 調用參數 支持字符串和數組 * @param string $layer 要調用的控制層名稱 * @param bool $appendSuffix 是否添加類名后綴 * @return mixed */ public static function action($url, $vars = [], $layer = 'controller', $appendSuffix = false) { $info = pathinfo($url);// 獲取 url 地址信息 $action = $info['basename'];// 獲取 action 方式 $module = '.' != $info['dirname'] ? $info['dirname'] : Request::instance()->controller(); // 獲取 中間值 module $class = self::controller($module, $layer, $appendSuffix);// 獲取 class 名稱 if ($class) {// 如果存在 class if (is_scalar($vars)) {// 如果是標準量//is_scalar — 檢測變量是否是一個標量 if (strpos($vars, '=')) {// strpos parse_str($vars, $vars);// 解析字符串//parse_str — 將字符串解析成多個變量 } else { $vars = [$vars];// 這個強轉換 漂亮 } } return App::invokeMethod([$class, $action . Config::get('action_suffix')], $vars); }//return App:: 驗證文件是否存在 } /** * 字符串命名風格轉換 * type 0 將Java風格轉換為C的風格 1 將C風格轉換為Java的風格 * @param string $name 字符串 * @param integer $type 轉換類型 * @param bool $ucfirst 首字母是否大寫(駝峰規則) * @return string */ public static function parseName($name, $type = 0, $ucfirst = true) {// 轉換字符串 風格的 一個小函數,如果1 就大寫,否則就小寫 if ($type) { $name = preg_replace_callback('/_([a-zA-Z])/', function ($match) { return strtoupper($match[1]); }, $name); return $ucfirst ? ucfirst($name) : lcfirst($name); } else { return strtolower(trim(preg_replace("/[A-Z]/", "_\\0", $name), "_")); } } /** * 解析應用類的類名 * @param string $module 模塊名 * @param string $layer 層名 controller model ... * @param string $name 類名 * @param bool $appendSuffix * @return string */ public static function parseClass($module, $layer, $name, $appendSuffix = false) {// 解析 Class 類名 $name = str_replace(['/', '.'], '\\', $name);// 替換類名 $array = explode('\\', $name);// 解析類資源 $class = self::parseName(array_pop($array), 1) . (App::$suffix || $appendSuffix ? ucfirst($layer) : ''); $path = $array ? implode('\\', $array) . '\\' : ''; return App::$namespace . '\\' . ($module ? $module . '\\' : '') . $layer . '\\' . $path . $class; }// 解析 類名 /** * 初始化類的實例 * @return void */ public static function clearInstance() { self::$instance = []; }// 初始化,就是 清空實例 } /** * 作用范圍隔離 * * @param $file * @return mixed */ function __include_file($file) { return include $file; }// 封裝,暫時不用加載那個 commons.php function __require_file($file) { return require $file; }// 封裝,默認加載 ~~~
                  <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>

                              哎呀哎呀视频在线观看